Shop OBEX P1 Docs P2 Docs Learn Events
Understanding DATA — Parallax Forums

Understanding DATA

JeraldJerald Posts: 3
edited 2009-08-07 04:56 in BASIC Stamp
Hello, my name is Jerald and I recently purchased the lynxmotion AL5C robotic arm. I'm trying to control the arm using the Parallax Super Carrier board with a BS2px chip. I'm using the Lynxmotion RIOS software to program the arm's sequences then using the same program to convert these sequences to BS2 language.

I'm programming several different sequences and individually converting them to Stamp. One converted and downloaded to the Stamp, they work great..induvidually. However, what i'd like to do is make each sequence its own subroutine that can be called whenever needed by the code and/or program.

The problem I'm having is how the individual servo positions are saved in the DATA format onto the EEPROM. I think the arm's servo controller gets the data confused and reacts strangely to the code I have listed below. In the code, I have the main program set up to call one subroutine, followed by another and stop. What actauul happens once the program is running is it will run the first subroutine fine..then it will run it again..then it will start the second routine..and hlf way through the second routine, it stops and seemingly locks up.

I·think the program the way it is is storing all sequences in the same DATA locations and getting confused which DATA is the right one to use for a particular sequence. I'm not really knowlegable about how the DATA nd READ commands interact with each other in the Stamp language and the examples in the Syntax manual are not too descriptive.

How can I easily seperate all data so that only the right data is being used by a subroutine?

Here's a copy of a test program I'm playing with right now:

' FuctionalTest2.bs2
' {$STAMP BS2}
' {$PBASIC 2.5px}
·
'This program tests the functionality of using subroutines to control the arm
'
Main Program

Main:
· GOSUB Num1
· PAUSE 500
· GOSUB Num2
· PAUSE 500
END
·
'
Subroutines

Num1:
· DATA· 155, 195, 210, 164, 142, 144, Word 1000, Word 0
· DATA· 155, 195, 210, 164, 142, 144, Word 30, Word 0
· DATA· 155, 171, 202, 164, 142, 144, Word 330, Word 0
· DATA· 155, 171, 169, 148, 142, 144, Word 660, Word 0
· DATA· 155, 188, 188, 148, 142, 144, Word 300, Word 0
· DATA· 155, 195, 210, 162, 142, 144, Word 300, Word 0
·
· idxa··· VAR·· Word
· time1a· VAR·· Word
· pause1a VAR·· Word
· pos1a·· VAR·· Byte
· pos2a·· VAR·· Byte
· pos3a·· VAR·· Byte
· pos4a·· VAR·· Byte
· pos5a·· VAR·· Byte
· pos6a·· VAR·· Byte
·
· SSC32a· CON·· 15
· PAUSE 500
·
···· FOR idxa = 0 TO 5
····· READ idxa * 10, pos1a
····· READ idxa * 10 + 1, pos2a
····· READ idxa * 10 + 2, pos3a
····· READ idxa * 10 + 3, pos4a
····· READ idxa * 10 + 4, pos5a
····· READ idxa * 10 + 5, Pos6a
····· READ idxa * 10 + 6, Word time1a
····· READ idxa * 10 + 8, Word pause1a
····· SEROUT SSC32a, 84, [noparse][[/noparse]"#0P", DEC pos1a * 10, " #1P", DEC pos2a * 10, " #2P", DEC pos3a * 10,
······· " #3P", DEC pos4a * 10," #4P", DEC pos5a * 10, " #5P", DEC pos6a * 10," T", DEC time1a, 13]
····· PAUSE time1a + pause1a
··· NEXT
RETURN
·
Num2:
· DATA· 156, 195, 209, 161, 142, 144, Word 1000, Word 0
· DATA· 156, 170, 171, 149, 142, 144, Word 540, Word 0
· DATA· 141, 170, 171, 149, 142, 144, Word 120, Word 0
· DATA· 172, 170, 171, 149, 142, 144, Word 240, Word 0
· DATA· 172, 165, 187, 154, 142, 144, Word 450, Word 0
· DATA· 145, 165, 187, 154, 142, 144, Word 300, Word 0
· DATA· 145, 173, 204, 163, 142, 144, Word 210, Word 0
· DATA· 183, 173, 204, 163, 142, 144, Word 360, Word 0
· DATA· 156, 173, 204, 163, 142, 144, Word 240, Word 0
· DATA· 156, 195, 210, 163, 142, 144, Word 330, Word 0
· DATA· 156, 195, 210, 157, 142, 144, Word 90, Word 0
·
··· idx··· VAR·· Word
· time1· VAR·· Word
· pause1 VAR·· Word
· pos1·· VAR·· Byte
· pos2·· VAR·· Byte
· pos3·· VAR·· Byte
· pos4·· VAR·· Byte
· pos5·· VAR·· Byte
· pos6·· VAR·· Byte
·
· SSC32· CON·· 15
· PAUSE 500
·
··· FOR idx = 0 TO 10
····· READ idx * 10, pos1
····· READ idx * 10 + 1, pos2
····· READ idx * 10 + 2, pos3
····· READ idx * 10 + 3, pos4
····· READ idx * 10 + 4, pos5
····· READ idx * 10 + 5, Pos6
····· READ idx * 10 + 6, Word time1
····· READ idx * 10 + 8, Word pause1
····· SEROUT SSC32, 84, [noparse][[/noparse]"#0P", DEC pos1 * 10, " #1P", DEC pos2 * 10, " #2P", DEC pos3 * 10,
······· " #3P", DEC pos4 * 10," #4P", DEC pos5 * 10, " #5P", DEC pos6 * 10," T", DEC time1, 13]
····· PAUSE time1 + pause1
··· NEXT
RETURN
·
Any help would be greatly appreciated. This is for a school project and nobody in our school is familiar with this language to give some insight.
Thank you,
Jerald yeah.gif

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2009-08-06 16:33
    Num1 and Num2 are the starting locations of the corresponding DATA tables, but your FOR / NEXT loops don't take that into account. Try changing the first one into:

    FOR idx = Num1 TO Num1+5

    and the second one into:

    FOR idx = Num2 TO Num2+10

    Get used to reading about any confusing or new statement (like DATA and READ) in the Stamp Editor help files or the downloadable Basic Stamp Syntax and Reference Manual. There's a chapter on each in the Manual.

    www.parallax.com/tabid/440/Default.aspx
  • SRLMSRLM Posts: 5,045
    edited 2009-08-06 16:49
    First off, in the future please attach the program using the attachment manager (instead of cutting and pasting it into the post). It makes it easier for us to help you.

    I think your program is messing up because both routines use the same address to start at (address 0). Anyway, here is how I would do it:

    To start, you should probably group all your variable declarations and data declarations at the top of the program. It makes it easier to maintain and see what you have.

    Next, you should name each sequence (of the five or ten steps) when you DATA it, and perhaps include a spot (the first one) dictating the number of steps that you have in the sequence (in your program, it would be 5 or 10). Something like this:

    Sequence1 DATA 5              'Five steps long
      DATA  155, 195, 210, 164, 142, 144, Word 1000, Word 0
      DATA  155, 195, 210, 164, 142, 144, Word 30, Word 0
      DATA  155, 171, 202, 164, 142, 144, Word 330, Word 0
      DATA  155, 171, 169, 148, 142, 144, Word 660, Word 0
      DATA  155, 188, 188, 148, 142, 144, Word 300, Word 0
      DATA  155, 195, 210, 162, 142, 144, Word 300, Word 0
    
    



    As a side note, you can probably get rid of the last word in your DATA. If it's always zero, why have it?

    Next, you declare a set of variables (using VAR) twice, even though they are almost identical. You only need one set. Why only one set?

    With a little bit of creativity, you only need on subroutine (which I'll call "Move") that takes a "parameter". I put in it quotes since PBASIC doesn't support parameters, but essentially that what it is. To make it work this way, you'll need to add a variable "pointer" which will give the address of the start of the movement sequence. Then, inside of your main function, you say something like this:

    main:
       pointer = Sequence1
       GOSUB Move
       ... 'other stuff
    



    You movement routine then examines this pointer variable, and gets the number of steps in the movement. It drops into a for loop and does it's thing, then it can return.

    If you do it this way, then you'll be able to have many more sequences since each additional sequence takes a minimum amount of EEPROM space (which is at a premium).

    Finally, look up the DEBUG command. It's amazingly helpful to just know where the program is and what a variable's value is.
  • JeraldJerald Posts: 3
    edited 2009-08-06 19:06
    Cool, thanks guys! As soon as I can I'll try out your suggestions.

    Thanks again,
    Jerald
  • JeraldJerald Posts: 3
    edited 2009-08-07 02:03
    I tried changing my code a bit, but it causes completely undesired results.

    Here's what I have:
    ' FuctionalTest2.bs2
    ' {$STAMP BS2px}
    ' {$PBASIC 2.5}
     
    'This program tests the functionality of using subroutines to control the arm
     
    sequence1 DATA 5                          'Five steps long
      DATA   155, 195, 210, 164, 142, 144, Word 1000, Word 0
      DATA   155, 195, 210, 164, 142, 144, Word 30, Word 0
      DATA   155, 171, 202, 164, 142, 144, Word 330, Word 0
      DATA   155, 171, 169, 148, 142, 144, Word 660, Word 0
      DATA   155, 188, 188, 148, 142, 144, Word 300, Word 0
      DATA   155, 195, 210, 162, 142, 144, Word 300, Word 0
     
    sequence2 DATA 10                       'Ten steps long
      DATA  156, 195, 209, 161, 142, 144, Word 1000, Word 0
      DATA  156, 170, 171, 149, 142, 144, Word 540, Word 0
      DATA  141, 170, 171, 149, 142, 144, Word 120, Word 0
      DATA  172, 170, 171, 149, 142, 144, Word 240, Word 0
      DATA  172, 165, 187, 154, 142, 144, Word 450, Word 0
      DATA  145, 165, 187, 154, 142, 144, Word 300, Word 0
      DATA  145, 173, 204, 163, 142, 144, Word 210, Word 0
      DATA  183, 173, 204, 163, 142, 144, Word 360, Word 0
      DATA  156, 173, 204, 163, 142, 144, Word 240, Word 0
      DATA  156, 195, 210, 163, 142, 144, Word 330, Word 0
      DATA  156, 195, 210, 157, 142, 144, Word 90, Word 0
     
      pointer  VAR   Word
      idx      VAR   Word
      time1    VAR   Word
      pause1   VAR   Word
      pos1     VAR   Byte
      pos2     VAR   Byte
      pos3     VAR   Byte
      pos4     VAR   Byte
      pos5     VAR   Byte
      pos6     VAR   Byte
    
      SSC32  CON   15
    
    '----------- Main Program ------------
    Main:
      pointer = sequence1
      GOSUB Num1
      PAUSE 500
      pointer = sequence2
      GOSUB Num2
      PAUSE 500
    END
    '----------- Subroutines --------------
    Num1:
      PAUSE 500
        FOR idx = 0 TO 5
        GOSUB code
         DEBUG "Douche Bag", CR
        NEXT
    RETURN
     
    Num2:
      PAUSE 500
        FOR idx = 0 TO 10
        GOSUB code
        NEXT
    RETURN
     
    Code:
          READ idx * 10, pos1
          READ idx * 10 + 1, pos2
          READ idx * 10 + 2, pos3
          READ idx * 10 + 3, pos4
          READ idx * 10 + 4, pos5
          READ idx * 10 + 5, Pos6
          READ idx * 10 + 6, Word time1
          READ idx * 10 + 8, Word pause1
          SEROUT SSC32, 84, [noparse][[/noparse]"#0P", DEC pos1 * 10, " #1P", DEC pos2 * 10, " #2P", DEC pos3 * 10,
            " #3P", DEC pos4 * 10," #4P", DEC pos5 * 10, " #5P", DEC pos6 * 10," T", DEC time1, 13]
          PAUSE time1 + pause1
    RETURN
    

    ·Would it maybe work better if I put the "pointer =" statement in the actual subroutine code?

    Thanks,

    Jerald
    burger.gif··
  • SRLMSRLM Posts: 5,045
    edited 2009-08-07 04:56
    The purpose of making the named blocks of actions with the step count was to have one movement routine. The pseudo code is something like this:

    pointer = ExtendHand         'Extend hand is the sequence of steps in DATA
    GOSUB Move
    pointer = WaveHand
    GOSUB Move
    pointer = ThrowGrenade
    GOSUB Move
    
    ....
    
    Move:
    stepcounter = memory[noparse][[/noparse]pointer]    'get the number of steps in the sequence
    pointer = pointer + 1                   'Go to the first step
    ...                                              ' The whole movement routine with read and serout, etc.
    
    



    It wouldn't help to put the pointer= in the subroutine, since that variable supposed to tell the subroutine where to look for the data it needs to move the arm.

    You still need to think about what Mike said. You don't take into account the different starting positions of the various sequences.

    Your code says "DEBUG "Douche Bag", CR". For a little bit of professionalism, you could instead print out something like "In Num1 Subroutine:".

    The best thing to do is to step through the program as if you were the BS2. Start at the first line, and work through each and every line. If you don't understand exactly what the code on that line is doing, then look it up. For me, a printout of the code helps.
Sign In or Register to comment.