Shop OBEX P1 Docs P2 Docs Learn Events
Programming Help, Please (Vector Compass) — Parallax Forums

Programming Help, Please (Vector Compass)

freq42freq42 Posts: 18
edited 2004-10-02 15:03 in BASIC Stamp
·· Hello,
I am in the prose’s of setting up a vector compass electronic module from Jameco #126703 mfg#v2x
To a basic stamp 2 board with a LCD, Serial-interface-module for parallel displays from Jameco #157981 mfg#1616b-05a-100
This is my first problem, my rctime when debug'd has 5 to 6 digit's "ok" but my lcd only shows me 3 of them 0 to 256 I think it's only showing 8 bit's
And I need it to show at least 10 bit's to get 4000.
The other problem I have is the v2x output format. It has a synchronous serial port four communications. The
Output can be BCD or Binary. For BCD, the first six Bits are zeroes; for binary, the first seven bits are zeroes. After these zeroes the first bit out of the·vector is the most significant bit and the last bit out is the least significant bit {example a bcd of 359 degrees is 0000001101011001 and the binary bit's are 0000000101100111} I want to have the stamp reed from the v2x and print it on the lcd in dec.
My problem is I am new to basic stamp and don’t know how to right the cod to read the v2x 10 bit out put·and display it on the lcd.
I am a wizard @ hardware but not software. I am a ham radio operator and have countless projects under my belt
5 of them with the basic stamp2.
The code is not complete yet but this is what I have sow fare. It’s not perfect and nether is my spelling.
If you all could help me I would apresheat it.
Thank you.turn.gif··




' {$STAMP BS2}
' Program:SERIL LCD 2.BS2
' This program demonstrates fundamental techniques of driving
' PVC160204AYL serial LCDs in BASIC and a v2x vector compass chip from the BASIC Stamp II.
' It assumes·that the PVC160204AYL is connected to I/O pin P0 of the Stamp, and
' that it is set for 9600 bps.
' It assumes·that the V2X output ·is connected to I/O pin p2
' Start by defining some useful constants for the Backpack.
'
N9600 CON $4054 ' Baudmode-9600 bps inverted. Use $40F0 for BS2-SX.
I CON 254 ' Instruction prefix value.
time VAR Word
time2 VAR Word
CLR CON 1 ' LCD clear-screen instruction.
h CON 2 'move cursor to top/left character position
v CON 14 'turn on visible underline cursor
LINE2 CON 192 ' Address of 1st char of 2nd line.
L1_C7 CON 135 ' Address of line 1, character 7.
L1_c11 CON 139'··················· character 11.
L2_c11 CON 203
SEROUT 0,n9600,[noparse][[/noparse]96,i]
PAUSE 1
Again:
' Now clear the screen in case there's text left from a previous
' run of the program. Note that there's a 1-second PAUSE prior to
' sending any data to the Backpack. This gives the Backpack plenty
' of time to initialize the LCD after power up.
SEROUT 0,n9600,[noparse][[/noparse]1,2] ' Clear the LCD screen and home.
PAUSE 1
'
RCTIME---frum-mast
· HIGH 7········· 'Discharge the cap
· PAUSE 10··········· 'for·10 ms.
· RCTIME 7, 1, time
'
PrintIt Subroutine
SEROUT 0,n9600,[noparse][[/noparse]"HEADDING· ",DEC4 B2,223,CR,"AZIMUTH··· ",223]
B2 = time ' this will be the new vector compass memory in b2 four the headding.
'B3 = time2· ' set this up when the azimuth is set up using rctime.
PAUSE 100 ' Slow the loop down.
GOTO Again ' Repeat endlessly.

Post Edited By Moderator (Jon Williams) : 9/16/2004 5:54:23 PM GMT

Comments

  • Jon WilliamsJon Williams Posts: 6,491
    edited 2004-09-16 17:52
    You are using the internal variable B2 mixed with named variables (e.g. "time") -- this is a VERY BIG NO-NO·nono.gif·

    You are probably destroying one of the named variables, and B2 is only eight bits when your time variable is 16 bits. Change your "DEC4 B2" section to "DEC4 time" and that will, at least, display the time variable on your LCD.

    Get rid of any references to internal variables (B0 - B25, W0 - W13) in your BS2 programs and you will have a lot more success.

    Hint: Be sure to include a proper subject line for your posts (I've done that for you this time) -- you will get more help because many forum members skip "No Subject" posts.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
    Dallas Office


    Post Edited (Jon Williams) : 9/16/2004 5:55:15 PM GMT
  • freq42freq42 Posts: 18
    edited 2004-09-16 20:49
    Thank you Jon,
    When I posted it I real lizd I four got the heading.
    I did what you told me and it works now I just need to find how to get the data off the V2C card.
    I look't in the book that cam with it and it has no mention of baud rate in it???
    This is the link four the book http://www.jameco.com/wcsstore/Jameco/Products/ProdDS/126703.PDF
    I would lick it to run in master mode or slave mode. The extra lead’s hi is not a problem I would just need CAL to pin14 and RESET to pin15 four further programming bolth pin's will be tied hi and pulled low by the stamp.
    It look’s like I need 7 pins four master mode or 3 four slave mode?
  • freq42freq42 Posts: 18
    edited 2004-09-16 21:58
    found this and i am trying to convert it to bs2 culd you help???
    with a littel bit of hacking i think this will worck for me i think.

    ' {$STAMP BS2}
    '
    ' Basic Stamp BS1-IC interfaced with Vector 2X Compass Module.
    '
    ' Makes 256 compass bearing measurements at about 5 second intervals.
    '
    ' Vector 2X is reset, _PC is brought momentarily low, _SS is brought
    ' low and 16 bits of data are read. Lower 10 bits are displayed in
    ' hexadecimal.
    '
    ' The bearing is also converted to natural binary and displayed.
    '
    ' Peter Anderson, MSU, Dec 31, '96

    reading VAR W0
    n VAR B2
    m VAR B3

    'base_10 CON W2

    RESET CON 3
    SCLK CON 2
    _SS CON 1
    _PC CON 0

    EOC CON 7
    da CON 6

    DIRS=%00001111
    INS=%00001111

    top:
    FOR n=0 TO 255
    RESET=0 ' reset compass module
    PAUSE 10
    RESET=1
    PAUSE 100
    _PC=0 ' _PC brought momentarily low
    PAUSE 10
    _PC=1

    PAUSE 100
    _SS=0 ' slave select brought low

    scan:
    IF EOC=0 THEN scan ' wait until conversion is completed
    GOSUB get_reading ' fetch 16 bit reading
    reading=reading & $3ff ' only the 10 least sig bits
    DEBUG reading ' display result in base 10

    GOSUB convert_base_10 ' converts reading to base 10
    DEBUG base_10

    _SS=1 ' reading done
    PAUSE 500 ' wait for next measurement
    NEXT
    END

    get_reading:
    ' reads each of 16 bits from SDO, most significant bit first
    reading=0
    FOR m=0 TO 15
    PAUSE 20 ' negative going clock pulses
    SCLK=0
    PAUSE 20
    SCLK=1 ' DATA is read after positive clock
    reading=reading * 2 + DATA ' shift left and add new bit
    NEXT
    RETURN

    convert_base_10:
    ' convert BCD to natural binary
    base_10 = reading / 256 * 100 ' hundreds
    reading = reading // 256
    base_10 = reading / 16 * 10 + base_10 ' tens
    reading = reading // 16
    base_10 = reading + base_10 ' units
    RETURN
  • dandreaedandreae Posts: 1,375
    edited 2004-09-16 22:05
    Hello,

    I was looking on www.google.com and I typed in BASIC Stamp and Vector 2x and noticed that there was quite a few topics regarding the BASIC Stamp and the Vector 2x.· I'm not sure if it has the information that you are looking for?· It's worth a try.

    Dave
  • dandreaedandreae Posts: 1,375
    edited 2004-09-16 22:10
    I found this link that has a PDF file with the sample code for the BS2 and the Vector 2x, here it is:· http://www.robotics.com/arobot/vector.pdf


    Dave
  • dandreaedandreae Posts: 1,375
    edited 2004-09-16 22:13
    Try this code:

    '

    'vector.bs2 Arrick Robotics www.robotics.com
    'This routine shows how to read data from the
    'Vector 2x compass.
    'compass signals.
    select con 2 'select signal.
    sdo con 3 'serial data out.
    sclk con 4 'clock signal.
    rst con 5 'reset signal.
    'Other.
    speaker con 9 'speaker pin.
    heading var word 'heading variable.
    setup
    output select 'set pin direction.
    output sclk
    output rst
    input sdo
    low speaker 'shut off the speaker.
    gosub compinit 'initialize the compass.
    main
    gosub getcomp 'get the compass heading.
    debug dec ? heading 'Display heading.
    pause 500 'wait a sec.
    goto main 'loop for ever.
    '

    'this routine initializes the Vector 2x compass.
    '
    compinit
    high sclk
    high select 'make sure this is high.
    low rst 'lower reset pin.
    pause 15 'wait 15 ms.
    high rst 'raise reset pin.
    pause 200 'wait a bit.
    return 'done.
    '

    'This routine gets the heading from the Vector 2x
    'compass and places it in the variable heading.
    '
    getcomp
    low select 'start the Vector 2x.
    pause 200 'wait for heading.
    heading = 0 'clear variable.
    shiftin sdo,sclk,msbpre,[noparse][[/noparse]heading\16]
    'get the data from Vector 2x.
    high sclk 'reset pins.
    high select
    return 'done.
    Dave

  • freq42freq42 Posts: 18
    edited 2004-09-16 22:49
    thank you dave ill giv it a try.
  • freq42freq42 Posts: 18
    edited 2004-09-17 06:59
    thank you Dave that solved 90% of my programing. now i just have to tack the heading's output's "0,45,90,135,180,225,270,315,360" and turn it into "n,ne,e,se,s,sw,w,nw,n" then giv it a tag name of heading2.
    perhaps a lookdown and lookup is in order hear?
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2004-09-17 12:49
    Since you want to convert to string output, you cand divide your heading by 45 to get a pointer for a strings that are defined in DATA statement. Something like this:

    Headings DATA "N NEE SES SWW NW"

    ...

    Show_Heading:
    pntr = heading / 45
    FOR idx = 0 TO 1
    READ pntr + idx, char
    DEBUG char
    NEXT
    RETURN


    Notice that the each heading requires two characters -- hence the spaces in the DATA statement string. Of course, you can replace the DEBUG instruction with SEROUT if you're using an external display.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
    Dallas Office
  • freq42freq42 Posts: 18
    edited 2004-09-17 14:37
    wuld this be right?
    evry 90% is a letter?

    ' {$STAMP BS2}
    '
    'seril lcd with v2x.bs2 Bobby Petersen http://69.86.31.158
    'This routine shows how to read data from the
    'Vector 2x compass.
    'compass signals.
    select CON 2 'select signal.
    sdo CON 3 'serial data out.
    sclk CON 4 'clock signal.
    rst CON 5 'reset signal.
    'Other.
    index VAR Word
    N9600 CON $4054 ' Baudmode-9600 bps inverted. Use $40F0 for BS2-SX.
    I CON 254 ' Instruction prefix value.
    time VAR Word
    CLR CON 1 ' LCD clear-screen instruction.
    L1_C7 CON 135 ' Address of line 1, character 7.
    L1_c11 CON 139' , character 11.
    L2_c11 CON 203
    heading VAR Word 'heading variable.
    HEADING2 VAR Word
    SEROUT 0,n9600,[noparse][[/noparse]96,i]'set SIM to 16x2 fore the LCD
    PAUSE 1
    setup
    OUTPUT select 'set pin direction.
    OUTPUT sclk
    OUTPUT rst
    INPUT sdo
    GOSUB compinit 'initialize the compass.
    main
    GOSUB getcomp 'get the compass heading.
    'DEBUG DEC ? heading 'Display heading.
    PAUSE 500 'wait a sec.
    GOTO main 'loop for ever.
    '
    'this routine initializes the Vector 2x compass.
    '
    compinit
    HIGH sclk
    HIGH select 'make sure this is high.
    LOW rst 'lower reset pin.
    PAUSE 15 'wait 15 ms.
    HIGH rst 'raise reset pin.
    PAUSE 200 'wait a bit.
    RETURN 'done.
    '
    'This routine gets the heading from the Vector 2x
    'compass and places it in the variable heading.
    '
    getcomp
    LOW select 'start the Vector 2x.
    PAUSE 200 'wait for heading.
    heading = 0 'clear variable.
    SHIFTIN sdo,sclk,MSBPRE,[noparse][[/noparse]heading\16]'get the data from Vector 2x.
    HIGH sclk 'reset pins.
    HIGH select
    '
    ' this will tack the heading and asin it leters
    pntr VAR Word
    idx VAR Word
    Headings DATA "N E S W "

    Show_Heading:
    pntr = heading /90
    FOR idx = 0 TO 1
    READ pntr + idx, heading2



    '
    ' This program demonstrates fundamental techniques of driving
    ' PVC160204AYL serial LCDs in BASIC from the BASIC Stamp II. It assumes
    ' that the PVC160204AYL is connected to I/O pin P0 of the Stamp, and
    ' that it is set for 9600 bps.
    ' Start by defining some useful constants for the Backpack.
    '
    ' Now clear the screen in case there's text left from a previous
    ' run of the program. Note that there's a 1-second PAUSE prior to
    ' sending any data to the Backpack. This gives the Backpack plenty
    ' of time to initialize the LCD after power up.
    SEROUT 0,n9600,[noparse][[/noparse]1,2] ' Clear the LCD screen.
    PAUSE 1
    '
    RCTIME---from-mast
    HIGH 7 'Discharge the cap
    PAUSE 10 'for 9 ms.
    RCTIME 7, 1, time
    '
    PrintIt Subroutine
    SEROUT 0,n9600,[noparse][[/noparse]"HEADDING ",DEC heading ,223,heading2,CR,"AZIMUTH ",DEC time,223]

    PAUSE 1 ' Slow the loop down.
    'GOTO getcomp ' Repeat endlessly.
    RETURN 'dune.
  • freq42freq42 Posts: 18
    edited 2004-09-17 14:51
    ? if i devid by 45 and use it with the data "n ne e se s sw w nw " the lcd onle shows the first leter of each data?
  • freq42freq42 Posts: 18
    edited 2004-09-17 15:02
    if i use the program this way i get it right on the lcd. "

    Headings DATA "NESW"

    Show_Heading:
    pntr = heading /90
    FOR idx = 0 TO 1
    READ pntr + idx, heading2
    if i left it "Headings DATA "N E S W "" i wuld have to devide by 51.428571 to show the right way.
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2004-09-17 16:37
    You should always test new code OUTSIDE your application before adding it.· After considering your requirements and your original desire for eight cardinal (or is it ordinal?) points, I came up with this routine.· It offsets the compass by 22 degrees so that North is indicated when the heading is between 339 and 22 degrees (see graphic for explanation).

    ' {$STAMP BS2}

    hdng··· VAR···· Word
    pntr··· VAR···· Nib
    idx···· VAR···· Nib
    char··· VAR···· Byte

    HdgStr· DATA··· "N NEE SES SWW NW"

    Main:
    · FOR hdng = 0 TO 359
    ··· DEBUG HOME, DEC3 hdng, " "
    ··· LOOKDOWN hdng, <=[noparse][[/noparse]22,67,112,157,202,247,292,337,360], pntr
    ··· pntr = pntr // 8 * 2
    ··· FOR idx = 0 TO 1
    ····· READ (HdgStr + pntr + idx), char
    ····· DEBUG char
    ··· NEXT
    ··· PAUSE 500
    · NEXT
    · GOTO Main

    Run this code on its own first, just so you know it works -- then you can add the working bits into your program.





    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
    Dallas Office


    Post Edited (Jon Williams) : 9/17/2004 4:48:46 PM GMT
    572 x 523 - 19K
  • freq42freq42 Posts: 18
    edited 2004-09-17 22:00
    ill give it a try and let you know.
    thank you.
  • freq42freq42 Posts: 18
    edited 2004-09-19 06:03
    Ok I tried it by it self then add it to the program with no luck, but that's all right do to the way I have it now it is fine four the job @ hand.
    Just have to set up the GPS on pin 16 then set up the math four the maidenhead grid squares.
    I still have not found a way to get the display to reed right when you first turn on the stamp, after you hit reset all works fine.
    I do thank you four all your help and continuing support.


    ' {$STAMP BS2}
    '
    'seril lcd with v2x.bs2 Bobby Petersen http://69.86.31.158
    'This routine shows how to read data from the
    'Vector 2x compass.
    'compass signals.

    select CON 2 'select signal.
    sdo CON 3 'serial data out.
    sclk CON 4 'clock signal.
    rst CON 5 'reset signal.
    'Other.
    GPS VAR Word
    index VAR Word
    N9600 CON $4054 ' Baudmode-9600 bps inverted. Use $40F0 for BS2-SX.
    SEROUT 0,n9600,[noparse][[/noparse]04,"Q"]'set SIM to 16x2 fore the LCD
    PAUSE 10
    I CON 254 ' Instruction prefix value.
    time VAR Word
    CLR CON 1 ' LCD clear-screen instruction.
    'L1_C0 CON 127 ' Address of line 1, character 7.
    'L1_c11 CON 139' , character 11.
    L2_c0 CON 192
    heading VAR Word 'heading variable.
    HEADING2 VAR Word

    setup
    OUTPUT select 'set pin direction.
    OUTPUT sclk
    OUTPUT rst
    INPUT sdo
    GOSUB compinit 'initialize the compass.
    main
    GOSUB getcomp 'get the compass heading.
    'DEBUG DEC ? heading 'Display heading.
    PAUSE 500 'wait a sec.
    GOTO main 'loop for ever.
    '
    'this routine initializes the Vector 2x compass.
    '
    compinit
    HIGH sclk
    HIGH select 'make sure this is high.
    LOW rst 'lower reset pin.
    PAUSE 15 'wait 15 ms.
    HIGH rst 'raise reset pin.
    PAUSE 200 'wait a bit.
    RETURN 'done.
    '
    'This routine gets the heading from the Vector 2x
    'compass and places it in the variable heading.
    '
    getcomp
    LOW select 'start the Vector 2x.
    PAUSE 200 'wait for heading.
    heading = 0 'clear variable.
    SHIFTIN sdo,sclk,MSBPRE,[noparse][[/noparse]heading\16]'get the data from Vector 2x.
    HIGH sclk 'reset pins.
    HIGH select
    '
    'this will let you calibrate the V2X


    '
    ' this will tack the heading and asin it leters
    pntr VAR Word
    idx VAR Word
    Headings DATA "NESW"

    Show_Heading:
    pntr = heading /90
    FOR idx = 0 TO 1
    READ pntr + idx, heading2



    '
    ' This program demonstrates fundamental techniques of driving
    ' PVC160204AYL serial LCDs in BASIC from the BASIC Stamp II. It assumes
    ' that the PVC160204AYL is connected to I/O pin P0 of the Stamp, and
    ' that it is set for 9600 bps.
    ' Start by defining some useful constants for the Backpack.
    '
    ' Now clear the screen in case there's text left from a previous
    ' run of the program. Note that there's a 1-second PAUSE prior to
    ' sending any data to the Backpack. This gives the Backpack plenty
    ' of time to initialize the LCD after power up.

    'SEROUT 0,n9600,[noparse][[/noparse]04,"q"]
    SEROUT 0,n9600, ' Clear the LCD screen.
    PAUSE 1
    SEROUT 0,n9600,[noparse][[/noparse] 12]
    PAUSE 1
    '
    RCTIME---from-mast
    HIGH 7 'Discharge the cap
    PAUSE 10 'for 9 ms.
    RCTIME 7, 1, time
    '
    PrintIt Subroutine

    SEROUT 0,n9600,[noparse][[/noparse]"HEADDING ",DEC heading ,223, heading2,10,CR,"AZIMUTH ",DEC time,223,10,CR,"GPS ",DEC5 Gps,10,CR,2]


    PAUSE 1 ' Slow the loop down.
    'GOTO getcomp ' Repeat endlessly.
    RETURN 'dune.
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2004-09-19 18:16
    Each time I looked at the code you posted I kind of scratched my head wondering if it would actually work -- so I pasted it into my editor and find that it doesn't (at least as posted).· As an electronics pro I'm sure you take great care in constructing your circuits; the same care, when applied to code, will give you the same results (works sooner with fewer bugs).· Your program seems to be suffering a bit from cut-and-paste-itis ... and we've all been there.· The posted code seems to have LCD constants for the SEETRON display, but you're using the one from Jameco that works differently.· Thank Goodness for the Internet and downloadable data sheets.

    I put on the kettle this morning, made some green tea, and decided to apply Parallax programming standards to your application to see if I could make it easier to work with (see the attached program -- but understand that I didn't have the parts to test it, so it may need adjusting).· You'll see that my version of your program takes advantage of PBASIC 2.5, is organized, and·uses named pins and values to make the core code easier to read.· I'd love to know if it works on your system without adjustment (that would make me smile).· Don't be concerned about the removal of some lines of code -- there are unnecessary bits of code in your program.· For example, you don't have to make a pin an output if you're going to be using HIGH and LOW with that pin, as these commands make the specified pin an output beforehand.· And you don't have to declare pins an input if they've not been previously used by other commands because the BASIC Stamp initializes everything to inputs.

    We developed our programming standards for internal use and for those that write books for us that include code.· You can get a copy of that standard here:

    http://www.parallax.com/dl/docs/prod/stamps/pbasicstyle.pdf

    I think --·since you said you're new to the BASIC Stamp -- that you'll find the standard easy to live with and very helpful as you design projects with greater complexity.· Have fun with your projects, and do keep everyone posted on your progress.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
    Dallas Office


    Post Edited (Jon Williams) : 9/19/2004 6:21:01 PM GMT
  • freq42freq42 Posts: 18
    edited 2004-09-19 21:06
    Each time you looked at the code I posted you kind of scratched your head wondering if it would actually work?
    Well i'm happy to say that yes it did work! In fact I that it work't reel good four the first time on my own with out a book to guide me. "Doing all this with your homework board from radio shack open box sale”. I look’t at your code and it look's lick it should work but the heading was erratic would not stay with in 2 degrees kept reading 585,876,27,650,66, xed, xed but it did salve my power up ruteen thaw. Ill goes back over the program I did, and with yours to generate a new code.
    I'm nearly dun with this project and will be submitting it to QST, NEWS "North East Weak Signal Group, and I think Servo/Nuts N volts.
    With a 5-year degree in robotic and computer repair you'd think I’d know code by now, but I don’t! But i’m learning. I could build this from scratch but why reinvent the wheel when a company has dunned it four you all ready! When it's all dun I'll look up the parts individually and design my own board then put it in a kit form four other hams/robotic teak’s to build and expand on.
  • freq42freq42 Posts: 18
    edited 2004-09-19 22:30
    Happy, Happy, Joy, Joy. Thank you Jon. After going over bolth of them I found the problem, hood would have thaut that leaving out one line of code " HIGH sclk 'reset pins. " would give sow much grief. I have now gone to a 20x4 LCD four-moor display area. Ill improve on what you gave me.
    I think its all-most time to start ordering parts and fabricating the boards to fit inside my home made 10GHZ transverter that's mounted on my truck.
    Soon ill post sum pictures on my web site hear at the house "it's good to cut out the middle man and have a host server that you don’t have to pay four on the internet".
  • cwolffcwolff Posts: 24
    edited 2004-09-25 05:37
    freq42...

    I'm hacking at a vx2e compass right now...if you could post your final code i'll modify it if needed to make the vx2e work and post my results.· Thank you!

    Regards,
    Christopher
  • cwolffcwolff Posts: 24
    edited 2004-09-25 06:12
    Just for s&g I modified your code to try to get my V2Xe to work.· Needless to say it spits out '0' for heading which is the same whether power is on or off shocked.gif

    Here's what I ended up with.· For clarification, here's my pinouts..

    Pin 1 on V2Xe - P15 on BS2P
    Pin 2 on V2Xe - P11 on BS2P
    Pin 3 on V2Xe - P12 on BS2P
    Pin 4 on V2Xe - P14 on BS2P
    Pin 5 on V2Xe - P13 on BS2P
    Pin 6 on V2Xe - P10 on BS2P
    Pin 7 on V2Xe - ground
    Pin 12 on V2Xe· - 3.3v
    Pin 14 on V2Xe - ground

    -modified code

    ' {$STAMP BS2p}
    '
    'seril lcd with v2x.bs2 Bobby Petersen http://69.86.31.158
    'This routine shows how to read data from the
    'Vector 2x compass.
    'compass signals.
    select··· CON 14······························ 'select signal.
    sdo······ CON 11································· 'serial data out.
    sclk····· CON 15································ 'clock signal.
    rst······ CON 10································· 'reset signal.
    GPS······ VAR Word
    index···· VAR Word
    PAUSE 10
    time····· VAR Word
    heading·· VAR Word··························· 'heading variable.
    HEADING2· VAR Word
    setup
    OUTPUT select······························ 'set pin direction.
    OUTPUT sclk
    OUTPUT rst
    INPUT sdo
    GOSUB compinit····························· 'initialize the compass.
    main
    GOSUB getcomp······························ 'get the compass heading.
    DEBUG DEC ? heading························ 'Display heading.
    DEBUG DEC ? HEADING2
    PAUSE 500·································· 'wait a sec.
    GOTO main·································· 'loop for ever.
    '
    'this routine initializes the Vector 2x compass.
    '
    compinit
    HIGH sclk
    HIGH select································ 'make sure this is high.
    LOW rst···································· 'lower reset pin.
    PAUSE 15··································· 'wait 15 ms.
    HIGH rst··································· 'raise reset pin.
    PAUSE 200·································· 'wait a bit.
    RETURN····································· 'done.
    '
    'This routine gets the heading from the Vector 2x
    'compass and places it in the variable heading.
    '
    getcomp
    LOW select································· 'start the Vector 2x.
    PAUSE 200·································· 'wait for heading.
    heading = 0································ 'clear variable.
    SHIFTIN sdo,sclk,MSBPRE,[noparse][[/noparse]heading\16]······· 'get the data from Vector 2x.
    HIGH sclk·································· 'reset pins.
    HIGH select
    '
    'this will let you calibrate the V2X

    '
    ' this will tack the heading and asin it leters
    pntr VAR Word
    idx VAR Word
    Headings DATA "NESW"
    Show_Heading:
    pntr = heading /90
    FOR idx = 0 TO 1
    READ pntr + idx, heading2
    PAUSE 1···································· 'Slow the loop down.
    RETURN····································· 'dune.
  • cwolffcwolff Posts: 24
    edited 2004-09-25 20:33
    Well it appears that the big difference between the V2X and V2xe is that the 'e' version requires certain commands to be sent to it.· A gentleman at the 'circuit cellar' built this v2xe into a robot and got the v2xe talking with the following C code.· If I can munge his code into PBASIC i'm sure we'd have a winner.

    //
    // MiniRover7_100.c
    //
    // Joe Miller
    //
    // DATE: 12/15/03
    //
    // Commands are received through the hardware UART at 9600bps.
    // This program Controls 2 R/C Servos using the PCA timer to generate 2 pulse
    // widths for standard RC type servos. Six drive motors are controlled in two
    // sets via dual H-bridge drivers.
    // SYSCLK frequency is 3.0625 MHz using 24.5MHz internal Osc divided by 8
    //
    // Commands:
    // ·'c'·Begin calibrate. 's' stops calibration. use 'r' or 'l' to rotate robot
    // ·'s'·Stop. stops robot motors and calibration process. Also sets bearing.
    // ·'r'·Rotate right (CW)
    //·'l' Rotate left (CCW)
    //·'t' stores present heading as a bearing point and move forward while tracking bearing point
    //·'f' move forward
    //·'h' select heading information as upload data
    //·'b' select raw sensor info as upload data
    //·'m' select heading and magnitude as upload data
    //·'o' upload data off
    //·'=' incriment bearing point by 5 degrees
    //·'-' decrement bearing point by 5 degrees
    //
    //
    // Target: C8051F330
    // Tool chain: KEIL C51 6.03 / KEIL EVAL C51
    //
    //
    //
    // Includes
    //
    #include <c8051f330.h>················ // SFR declarations.
    //
    // 16-bit SFR Definitions for 'F330
    //
    sfr16 DP······ = 0x82;················ // data pointer
    sfr16 TMR2RL·· = 0xca;················ // Timer2 reload value
    sfr16 TMR2···· = 0xcc;················ // Timer2 counter
    sfr16 PCA0CP0· = 0xfb;················ // PCA0 Module 0 Capture/Compare
    sfr16 PCA0CP1· = 0xe9;················ // PCA0 Module 1 Capture/Compare
    sfr16 PCA0···· = 0xf9;················ // PCA0 counter
    //
    // Global CONSTANTS
    //
    #define SYSCLK······ 3062500········· ·// SYSCLK frequency in Hz
    #define BAUDRATE···· 9600············· ·// Baud rate of UART in bps
    #define RTI_RATE· 10·····// RTI rate in milliseconds
    #define RTI_BASE· 0xffff - (SYSCLK * RTI_RATE / 1000 )·// Calculate timer2 reload value
    #define TIMING_OFFSET 0xffff - 766··// default timing window setting
    ··········// .25mS/.32653uS· = 766
    ··········// .25mS is good for Hitech servos
    #define GET_MODID·0x00····// Compass Command to get module ID
    #define BEG_SAMPLE_COMPASS 0x20···// Compass Command to begin sample
    #define GET_XSEN·0x22····// Compass Command to get X sensor raw data
    #define GET_YSEN·0x23····// Compass Command to get y sensor raw data
    #define GET_HDG··0x2D····// Compass Command to get Heading
    #define SVO_L_FWD·0xffff - 0x1680··// Left steering servo position for forward movement
    #define SVO_R_FWD·0xffff - 0xE00··// Right steering servo position for forward movement
    #define SVO_L_TURN ·0xffff - 0x900··// Left steering servo position for turning
    #define SVO_R_TURN ·0xffff - 0x1B80··// Right steering servo position for turning
    #define MAX_COMP·0x480····// Maximum steering allowed during tracking mode
    #define MOTOR_CW_TURN··0x4a··// Traction motor H-Bridge driver value for clockwise turn
    #define MOTOR_CCW_TURN··0x54··// ··...for CCW turn
    #define MOTOR_FWD···0x58··//·· ...for forward movement
    #define MOTOR_STOP···0xe1··//··· ...to stop the motors
    #define TRACKING_RATE·5····// Real time update rate
    #define HEADING_RATE·100····// Rate at which heading info is sent to host
    #define·HEADING··1·····// Heading mode for upload data
    #define RAW···2·····// Raw sensor mode
    #define MAG···3·····// magnitude mode
    ········//postion tracking control loop constants
    #define DERIV··100·····// Derivitive gain·
    #define PROP··250·····// Proportional gain
    #define INTG··10·····// Integral gain
    #define SyncChar·0xAA····// V2Xe packet start byte
    #define DataReady·0xAB····// V2Xe Data Ready character
    #define CommandOK·0xAE····// V2Xe command recieved and understood
    #define CMD_startcal·0x0a···// v2Xe start calibration process command
    #define CMD_stopcal··0x0b···// v2Xe stop calibration process command

    //
    // Defdef and Function PROTOTYPES
    //
    typedef unsigned char Uint8;···// 8 bit unsigned integer
    typedef unsigned int Uint16;···// 16 bit unsigned integer
    typedef signed int Sint16;····// 16 bit signed integer
    void RTI_ISR (void);
    void UART_ISR (void);
    void proc_cmd(void);
    void send_char(Uint8);
    void init_peripherals (void);
    void get_mag(void);
    void get_compass(void);
    void V2Xe_send(Uint8);
    void V2Xe_read(Uint8);
    void init_V2Xe(void);
    void update_host(void);
    void send16_host(Sint16);
    void track(void);
    //
    // Global VARIABLES
    //

    sbit·sync·=·0x95;··// Output to compass's Sync input
    sbit·drdy·=·0x96;··// Input for compass's Data Ready output
    sbit·ssnot·=·0x83;··// Output to compass's Slave Select(Not) input
    sbit·nCTS·=·0x90;··// Input from RF Modem's Clear To Send(Not) output
    sbit·sclk·= ·0x80;··// Output to compass's SPI serial data input
    sbit·mosi·=·0x82;··// Output to compass's· serial data output
    sbit·nsvo_pwr·=·0x97;·// Output. When low, power is enabled to the steering servos
    Uint16· bearing;··// Current Compass bearing to track
    Uint16·heading;··// Current Compass heading
    Sint16·error;···// Current heading error
    Sint16· error_last;··// Previous heading error
    Sint16· error_intg;··// Integral heading error
    Sint16· comp;···// heading error compensation
    Sint16 ·Xraw, Yraw;··// Raw sensor data
    Uint16 work, value;··// General Purpose reuable 16-bit unsigned variables
    Uint8·· field_mag;··// Magnetic field magnetude
    Uint8·sbuff;···// temporary storage of serial receiver data
    Uint8·V2Xe_ret[noparse][[/noparse]24];·// Return data from V2Xe compass is placed in here
    Uint8·V2Xe_out[noparse][[/noparse]24]; ·// Data to be sent to V2Xe compess
    Uint8·exponent;··// Exponent value from the compass heading floating point number
    Uint8·timer;···// reading capture interval timer
    Uint8·tracking_update;·// Count down vlaue to next direction tracking update
    Uint8·heading_update;·// time left until next heading update
    Uint8·data_package;·// use with HEADING, RAW, MAG constants to set data upload format
    bit·B_got_sdata;··// have some serial data to put away
    bit·B_proc_cmd;···// entire command string received. Ready to process command
    bit B_3byte_cmd;··// if set then current command is 3 bytes wide
    bit B_OnOff;···// servo pulse train on/off control
    bit B_MPcal;···// MPcal is running if this bit is set
    bit B_tic_cycle;··// periodic update flag set by RTI tic count underflow
    bit B_tracking;···// track heading mode
    bit B_calibrating;··// calibration mode
    bit B_Txstat;···// UART is busy sending current character
    Uint8·i,j,k;···// general purpose 8-bit unsigned variables


    //
    // MAIN Routine
    //
    //
    //
    void main (void)
    {
    ·· ····//Set initial values and conditions
    ··········// Disable Watchdog timer
    ·· ·PCA0MD &= ~0x40;·················· ·// WDTE = 0 (clear watchdog timer enable)
    ··· P0 &= ~1;··························
    ·· ·init_peripherals ();··············· // initialize peripherals
    ·ssnot = 1;·······// default pin states
    ·sync = 0;
    ··EA = 1;···························· // Enable global interrupts
    ·· ·B_OnOff = 0;······// servo default is Off
    ··
    ·timer=25; while(timer);····// small delay for power supply settling
    ·
    ·B_proc_cmd = 1;······// stimulate a stop command to be performed
    ·sbuff = 's';
    ·nsvo_pwr ·= 1;·····// Turn off steering servo power
    ·heading_update = HEADING_RATE;··// init heading update timer accumulator
    ·init_V2Xe();······// init and send V2Xe default data components
    ·get_compass();······// initialize heading
    //
    //·· ······· M A I N·· L O O P
    // ··This is an interrupt stimulated process. Interrupts· will generate
    //···the flags that the main loop will test and act apon.
    //
    ·while (1) ·{


    ···// if a command has been recieved
    ··if (B_proc_cmd)
    ···proc_cmd();

    ···// check if it is time to update the direction of the rover
    ···//··· (to track the previously set bearing)
    ··if (!tracking_update && B_tracking) {
    ···track();
    ···tracking_update = TRACKING_RATE;
    ···}

    ···// check if it is time to get another heading from the compass
    ··if (heading_update == 0· && data_package != 0) {
    ···if (!B_tracking) get_compass();
    ···update_host();
    ···heading_update = HEADING_RATE;
    ···}
    ·} //end of while(1)
    } // end of main()

    //
    // Process Command sent from host
    //
    void proc_cmd (void)
    {

    ·B_proc_cmd = 0;

    ·switch (sbuff)
    ·{
    ·case 'c':··// Start calibration
    ··V2Xe_out[noparse][[/noparse]0] = CMD_startcal ; V2Xe_out[noparse][[/noparse]1] = 0;
    ··V2Xe_send(3);
    ··B_calibrating = 1;···// Calibrating flag
    ··break;
    ·case 'r':··// Rotate Right
    ··nsvo_pwr ·= 0;···// Turn on steering servo power
    ··PCA0CP0··= SVO_L_TURN;·// Set wheel to turn
    ··PCA0CP1··= SVO_R_TURN;·// same for left
    ··PCA0CPM0·=·0xC2;··//
    ··PCA0CPM1·=·0xC2;··//
    ··timer = 25; while(timer);···// delay 1/2 second to allow wheel to come around
    ··timer = 25; while(timer);
    ··P1 = P1 & ~0x1e | MOTOR_CW_TURN;·// Set motors to CCW rotation pattern
    ··break;
    ·case 'l':··// Rotate Left
    ··nsvo_pwr ·= 0;···// Turn on steering servo power
    ··PCA0CP0··= SVO_L_TURN;·// Set wheel to turn
    ··PCA0CP1··= SVO_R_TURN;·// same for left
    ··PCA0CPM0·=·0xC2;··//
    ··PCA0CPM1·=·0xC2;··//
    ··timer = 25; while(timer);···// delay 1/2 second to allow wheel to come around
    ··timer = 25; while(timer);
    ··P1 = P1 & ~0x1e | MOTOR_CCW_TURN;·// Set motors to CCW rotation pattern
    ··break;
    ·case 't':··// Move Foward and stay on bearing "TRACK"
    ··nsvo_pwr ·= 0;···// Turn on steering servo power
    ··PCA0CP0··= SVO_L_FWD;·// Set wheel to middle (striaght)
    ··PCA0CP1··= SVO_R_FWD;·// same for left
    ··PCA0CPM0·=·0xC2;··//
    ··PCA0CPM1·=·0xC2;··//
    ··timer = 25; while(timer);·// delay 1/2 second to allow wheel to come around
    ··timer = 25; while(timer);
    ··P1 = P1 & ~0x1e | MOTOR_FWD;·// Set motors go straight
    ··get_compass();·····// set bearing
    ···bearing = heading;
    ··B_tracking = 1;
    ··break;
    ·case 'f':··// Move Foward
    ··nsvo_pwr ·= 0;···// Turn on steering servo power
    ··PCA0CP0··= SVO_L_FWD;·// Set wheel to middle (striaght)
    ··PCA0CP1··= SVO_R_FWD;·// same for left
    ··PCA0CPM0·=·0xC2;··//
    ··PCA0CPM1·=·0xC2;··//
    ··timer = 25; while(timer);·// delay 1/2 second to allow wheel to come around
    ··timer = 25; while(timer);
    ··P1 = P1 & ~0x1e | MOTOR_FWD;·// Set motors go straight
    ··break;
    ·case 's':··// Stop
    ··P1 &= MOTOR_STOP;··// Turn motors off
    ··nsvo_pwr = 1;···// Turn off power to servos to save energy
    ··if (B_calibrating)··// stop caibration cycle if it was running
    ···{
    ···B_calibrating = 0;
    ···V2Xe_out[noparse][[/noparse]0] = CMD_stopcal ; V2Xe_out[noparse][[/noparse]1] = 0;·// stop cal
    ···V2Xe_send(3);
    ···V2Xe_out[noparse][[/noparse]0] = 9 ; V2Xe_out[noparse][[/noparse]1] = 0; ····// save config
    ···V2Xe_send(3);
    ···}
    //··B_collect = 0;
    ··B_tracking = 0;···// discontinue tracking mode
    ··break;

    ·case 'p':··// Ping·

    ··send_char('p');
    //··while (1);···// set trap for debugging
    ··break;
    ·case 'h':··// set heading data package to send to host·

    ··data_package = HEADING;
    ··break;
    ·case 'b':··// set raw sensor data to send to host·

    ··data_package = RAW;
    ··break;
    ·case 'm':··// set heading and magnitude to send to host·

    ··data_package = MAG;
    ··break;
    ·case 'o':··// turn off data package to host·

    ··data_package = 0;
    ··break;

    ·case '-':··// turn off data package to host·

    ··if (bearing < 5 ) bearing += 360;
    ··bearing -= 5;
    ··break;

    ·case '=':··// turn off data package to host·

    ··if ((bearing += 5) > 360 ) bearing -= 360;
    ··break;
    ·default:
    ··break;
    ·} // end of switch case
    } // end of proc_cmd()

    //
    // Get Heading, raw sensor data and magnetude from V2Xe
    //
    void get_compass(void)
    {
    ·sync = 1;·····// reset V2Xe SPI port and buffers
    ·timer = 2; while(timer);·// wait at least 10mS
    ·sync = 0;

    ·V2Xe_out[noparse][[/noparse]0] = 0x04;···// fill output buffer with 'GetData' command
    ·V2Xe_out[noparse][[/noparse]1] = 0;
    ·V2Xe_send(3);····// send request
    ·V2Xe_read(22);····//·get response
    // IEEE 32 bit floating point to scaled integer convertion routine
    //·Integer will be scaled * 8 (i.e. 1 = 1/8, 2 = 1/4, 3 = 3/8, 4 = 1/2 ... 8 = 1.0 )
    //
    //·IEEE32 format:
    //
    //·33............24...23............16...15.............8...7..............0
    //·S E E E· E E E E·· E F F F· F F F F·· F F F F· F F F F·· F F F F· F F F F··
    //··· V2Xe_ret[noparse][[/noparse]2]······· V2Xe_ret[noparse][[/noparse]3]······· V2Xe_ret[noparse][[/noparse]4]······· V2Xe_ret[noparse][[/noparse]5]· for compass heading
    //··· V2Xe_ret[noparse][[/noparse]7]······· V2Xe_ret[noparse][[/noparse]8]······· V2Xe_ret[noparse][[/noparse]9]······· V2Xe_ret[noparse][[/noparse]10]· for magnetude
    //
    //
    // ·S = Sign
    //·E = Exponent
    //·F = Mantisa or Binary Fraction
    //
    //·Number = 1.F * 2^(E-127)
    //
    //·The code below will assume Sign = 0 (number is positive) for all headings
    //· all numbers are truncated to integers (not rounded)

    ····// if heading is less than 1 degree or zero (the IEEE32 version of zero)
    ·if ((V2Xe_ret[noparse][[/noparse]2] == 63 & V2Xe_ret[noparse][[/noparse]3] < 144) || V2Xe_ret[noparse][[/noparse]2] == 0 )·
    ··heading = 0;
    ·else
    ··{
    ··exponent = V2Xe_ret[noparse][[/noparse]2] * 2 + ((V2Xe_ret[noparse][[/noparse]3] > 127)? 1:0);·// move exponent into one byte
    ··heading = 1;·····// restore hidden 1.0 from normalized mantissa
    ··// this loop shifts fractional portion into integer heading until exponent reaches 2^(0) exponent
    ··while (exponent-- > 127)··// 127 is 2^0 (for unit values)
    ···{
    ···heading *= 2;····// shift data left into heading
    ···V2Xe_ret[noparse][[/noparse]3] *= 2;
    ···heading += ((V2Xe_ret[noparse][[/noparse]3] > 127)? 1: 0);
    ···V2Xe_ret[noparse][[/noparse]3] += ((V2Xe_ret[noparse][[/noparse]4] > 127)? 1 :0);
    ···V2Xe_ret[noparse][[/noparse]4] *= 2;
    ···}
    ··}

    ·// convert magnatude from floating point to Uint8 and scale to 1/128th units
    ·// were magnatude = 128 for a field magnatude of 1.000
    ·// ·····255 ······ 2.000·· magnetude
    ·//·····1······· 1/128th
    ·//·····0·······<1/128th
    ·// no need to test for absolute zero because it is not possible for magnatude
    ·// maximum number of bits shifted for this one is only 8 bits because magnatude is Uint8
    ·exponent = V2Xe_ret[noparse][[/noparse]7] * 2 + ((V2Xe_ret[noparse][[/noparse]8] > 127)? 1:0);·// move exponent into one byte
    ·field_mag = 1;·····// restore hidden 1.0 from normalized mantissa
    ·while (exponent-- > 120)··// 120 = (2^-7)binary which are 1/128th unit
    ··{
    ··field_mag *= 2;········// shift data left into magnatude variable
    ··V2Xe_ret[noparse][[/noparse]8] *= 2 ;·······// shift mantisa to read MSB
    ··field_mag += ((V2Xe_ret[noparse][[/noparse]8] > 127)? 1: 0);·// until exponent reaches 2^(-7) exponent
    ··}
    ·// rebuild Raw X and Y sensors data from Sint32 packed in a two-byte array into a single Sint16 value
    ·if (V2Xe_ret[noparse][[/noparse]14] > 127)
    ··Xraw = -1*((Sint16)(255 - V2Xe_ret[noparse][[/noparse]14]) * 256 + (255 - V2Xe_ret[noparse][[/noparse]15]) + 1) ;
    ·else
    ··Xraw = (Uint16)V2Xe_ret[noparse][[/noparse]14] * 256 + V2Xe_ret[noparse][[/noparse]15];
    ·if (V2Xe_ret[noparse][[/noparse]19] > 127)
    ··Yraw = -1*((Sint16)(255 - V2Xe_ret[noparse][[/noparse]19]) * 256 + (255 - V2Xe_ret[noparse][[/noparse]20]) + 1);
    ·else
    ··Yraw = (Sint16)V2Xe_ret[noparse][[/noparse]19] * 256 + V2Xe_ret[noparse][[/noparse]20];
    }

    //
    // Send data to V2Xe
    //
    //·len = # of bytes to send including sync, command and null
    //
    void V2Xe_send(Uint8 len)
    {
    ·ssnot = 0;
    ·SPIF = 0;······// reset SPI flag
    ·SPI0DAT = SyncChar;····// Send header command
    ·while (SPIF == 0);····// Wait until SPI finishes transfer
    ·i = 0; len--;
    ·do········// send string will null terminator
    ··{
    ··SPIF = 0x00;····// reset SPI flag
    ··SPI0DAT = V2Xe_out[noparse][[/noparse]i++];·// Send intended command character
    ··while (SPIF == 0);···// Wait until SPI finishes transfer
    ··}
    ·while (i < len);
    ·ssnot = 1;
    }
    //
    // Read data from V2Xe
    //
    //·len = # of return bytes including sync, command and null
    //
    void V2Xe_read(Uint8 len)
    {·········// Wait for return data header start character
    ·if (len < 3) len = 3;···// minimum len
    ·ssnot = 0;
    ·········// which starts with a SyncChar
    ·do
    ··{
    ··SPIF = 0;·····// reset SPI flag
    ··SPI0DAT = 0x00;····// Send dummy bits
    ··while (SPIF == 0);···// Wait until SPI finishes transfer
    ··}
    ·while (SPI0DAT != SyncChar);·// look for sync character

    ·i = 0;
    ·while (--len)·····// get all data
    ··{
    ··SPIF = 0;·····// reset SPI flag
    ··SPI0DAT = 0x00;····// Send dummy bits
    ··while (SPIF == 0);···// Wait until SPI finishes transfer
    ··V2Xe_ret[noparse][[/noparse]i++] = SPI0DAT;·// place V2Xe data into receive buffer
    ··}
    ·ssnot = 1;

    }
    //
    // This routine checks the Rover's heading and compares this to the previously
    //·· set bearing and adjusts the steering to compensate for the difference
    //·· a PID filter is utilized to increase response time
    //
    void track(void)
    ·{

    ·B_tic_cycle = 0;·····// reset Real Time clock periodic timer flag
    ·error_last = error;·····// save previous heading
    ·get_compass();······// get present compass heading

    ·error = (Sint16)(heading - bearing); // Calculate· Error
    ·if (error < -180) error += 360;·// adjust error for wrapping around the 360 degree point
    ·if (error >· 180) error -= 360;

    ·if (error_intg < MAX_COMP/INTG && error > 0)··// Calc integral of error
    ··error_intg += error;····//·· and limit final intgral output to +- 1000 counts
    ·if (error_intg > -MAX_COMP/INTG && error < 0)
    ··error_intg += error;

    ·// compute magnitude of steering correction required(compensation)
    ·comp = PROP * error + DERIV * (error_last - error) + INTG * error_intg;
    ·if (comp > MAX_COMP) ·comp = MAX_COMP;··// limit amount of compensation to MAX_COMP
    ·if (comp < -(MAX_COMP)) comp = -(MAX_COMP);
    ·PCA0CP0 = SVO_L_FWD + comp;······// Update new servo positions by setting the
    ·PCA0CP1 = SVO_R_FWD + comp;······//· PCA timer trippoint value
    ·PCA0CPM0·=·0xC2;·······//···· The PCA is in PWM mode
    ·PCA0CPM1·=·0xC2;·······//
    ·}
    //
    // Initialize V2Xe
    //
    void init_V2Xe(void)
    ·{
    ·ssnot = 0;······// select the V2Xe compass
    ·sync = 1;······// Reset the compass's SPI command/data stream
    ·timer = 2; while(timer);··// wait 10-20 ms
    ·sync = 0;
    ·timer = 2; while(timer);··// wait 10-20 ms

    ·V2Xe_out[noparse][[/noparse]0] = 0x03;··// command =· Set data components
    ·V2Xe_out[noparse][[/noparse]1] = 4;··// number of parameters
    ·V2Xe_out[noparse][[/noparse]2] = 5;··// request Heading data
    ·V2Xe_out[noparse][[/noparse]3] = 6;··// magnetude
    ·V2Xe_out[noparse][[/noparse]4] = 1;··// Raw X
    ·V2Xe_out[noparse][[/noparse]5] = 2;··// Raw Y
    ·V2Xe_out[noparse][[/noparse]6] = 0;··// end of string
    ·V2Xe_send(8);···// send request

    ·V2Xe_out[noparse][[/noparse]0] = 1;··// command = get module info
    ·V2Xe_out[noparse][[/noparse]1] = 0;··// end of string
    ·sync = 1;
    ·timer = 2; while(timer);··// wait 10-20 ms
    ·sync = 0;
    ·timer = 2; while(timer);··// wait 10-20 ms

    ·V2Xe_send(3);···// send request
    ·V2Xe_read(9);···// get response
    ·send_char(V2Xe_ret[noparse][[/noparse]5]);·// send module ID to host as indicator that robot is ready
    ·send_char(V2Xe_ret[noparse][[/noparse]6]);
    ·send_char(V2Xe_ret[noparse][[/noparse]7]);
    ·send_char(V2Xe_ret[noparse][[/noparse]8]);
    ·send_char(0x0d);···// CR
    ·send_char(0x0a);···// LF
    ·ssnot = 1;
    ·}
    //
    // Send data to host via RF modem
    //
    void send_char(Uint8 tx_char)
    ·{
    ·while(B_Txstat);····// wait for complete transmission
    ·while(nCTS);·····// do not send data to radio if its buffer is full
    ·TI0 = 0;
    ·SBUF0 = tx_char;
    ·B_Txstat = 1;·····// set transmission in progress flag
    ·}
    //
    // Send data package to host
    //
    void update_host(void)·{
    ·if (B_tracking) {··········// If in tracking mode
    ··send_char('B');
    ··send16_host((Sint16)bearing);·······// send present bearing value
    ··send_char(',');
    ··send_char('C');
    ··send16_host(comp);··········// and· present compensation value
    ··}

    ·if (data_package == HEADING || data_package == MAG) {·// If Heading or Magnutude values are requested
    ··if (B_tracking)
    ···send_char(',');
    ··send_char('H');···········// send Heading information
    ··send16_host((Sint16)heading);
    ··}

    ·if (data_package == MAG) {········// If Magnitude value is requested
    ··send_char(',');
    ··send_char('M');
    ··send16_host((Sint16)field_mag);·······// send magnitude
    ··}

    ·if (data_package == RAW) {········// If V2Xe raw magnetometer values are requested
    ··send16_host(Xraw);
    ··send_char(',');
    ··send16_host(Yraw);··········// send raw mag values
    ··}
    ·send_char(0x0d); ···// CR
    ·send_char(0x0a); ···// LF
    ·}
    //
    // Convert Sint16 value to ASCII and send to host
    //
    void send16_host(Sint16 dataV) {
    ·if (dataV < 0 ) {
    ··dataV *= -1;
    ··send_char('-');
    ··}
    ·work = dataV;
    ·if (work > 9999) {
    ··value = dataV / 10000;
    ··dataV = dataV % 10000;
    ··send_char(value + 0x30);
    ··}
    ·if (work > 999) {
    ··value = dataV / 1000;
    ··if(value) dataV = dataV % 1000;
    ··send_char(value + 0x30);
    ··}
    ·if (work > 99) {
    ··value = dataV / 100;
    ··if(value) dataV = dataV % 100;
    ··send_char(value + 0x30);
    ··}
    ·if (work > 9)·{
    ··value = dataV / 10;
    ··if(value) dataV = dataV % 10;
    ··send_char(value + 0x30);
    ··}
    ·send_char(dataV + 0x30);
    }

    //
    // Initialization Routine
    // This Code was generated using the Cygnal Configuration Wizard
    // I added some comments and minor alterartions
    //

    void init_peripherals (void)
    {
    //
    // Initialize Port and Crossbar settings
    //
    ··· //P0.0· -· SCK· (SPI0), Push-Pull,· Digital··To communicate with V2Xe Compass
    ··· //P0.1· -· MISO (SPI0), Open-Drain, Digital
    ··· //P0.2· -· MOSI (SPI0), Push-Pull,· Digital
    ··· //P0.3· -· Unused,···· Push-Pull,· Digital
    ··· //P0.4· -· TX0 (UART0), Push-Pull,· Digital
    ··· //P0.5· -· RX0 (UART0), Open-Drain, Digital
    ··· //P0.6· -· CEX0 (PCA),· Push-Pull,· Digital··Right Servo pulse output
    ··· //P0.7· -· CEX1 (PCA),· Push-Pull,· Digital··Left Servo pulse output
    ··· //P1.0· -· nCTS,· Push-Pull,· Digital···RF Modem control signal
    ··· //P1.1· -· A1,· Push-Pull,· Digital····H-Bridge Channel A bit 1
    ··· //P1.2· -· A2,· Push-Pull,· Digital····H-Bridge Channel A bit 2
    ··· //P1.3· -· B1,· Push-Pull,· Digital····H-Bridge Channel B bit 1
    ··· //P1.4· -· B2,· Push-Pull,· Digital····H-Bridge Channel B bit 2
    ··· //P1.5· -· SYNC,· Push-Pull,· Digital···To reset Compass
    ··· //P1.6· -· DRDY,· Open-Drain, Digital···From Compass Data Ready Pin
    ··· //P1.7· -· SVO_PWR,· Push-Pull,· Digital··Servo Power Enable
    ··· P0MDOUT···· = 0xDD;··// 1=push-pull, 0=Open drain
    ·P0···= ~0xDD;·// Open port bits for inputs and initialize outputs
    ··· P1MDOUT···· = 0xBF;··// same
    ·P1···= ~0xBF;
    ··· P0SKIP····· = 0x08;··// Skip around P0.3 to save for future function
    ··· XBR0······· = 0x03;··// bring SPI and UART functions routed to pins
    ··· XBR1······· = 0x42;··// bring CEX0,1 routed and enable Xbar

    //
    // Initialize Timer settings
    //
    ··· TCON······· = 0x40;··// Timer1 enabled. For Baud Rate generation
    ··· TMOD······· = 0x20;··// Timer1 Mode2, 8-bit auto reload
    ··· CKCON······ = 0x18;··// Timer1 and Timer2 to use SYSCLK with no prescaling,
    ··· TH1········ = 0x61;··// Timer1 reload value for 9600 Baud
    ··· TMR2CN····· = 0x04;··// Timer2 enabled and configured for 16-bit auto reload
    ··· TMR2RL····· = RTI_BASE;·// Timer2 reload value for 10mS RTI
    ·· ·TMR2··· ·= 0x0;··// set timer to beginning to allow time
    ·······//·for balance of init routines to execute
    ··

    //
    // Initialize PCA settings
    //
    ··· PCA0CN····· = 0x40;··// PCA counter enabled
    ·PCA0MD····· = 0x08;··// PCA to use SYSCLK , WDT disababled
    //·PCA0MD····· = 0x09;··// PCA to use SYSCLK , WDT disababled interrupt enabled
    ·······//· this makes the PCA freq 46Hz (21mS)
    ·PCA0CP0··= SVO_L_FWD;·// Set servo to middle of stoke (striaght)
    ·PCA0CP1··= SVO_R_FWD;·// same for left
    ··· PCA0CPM0··· = 0xC2;··// PCA channel 0 set to 16bit PWM
    ··· PCA0CPM1··· = 0xC2;··// PCA channel 1 set to 16bit PWM
    //
    // Initialize UART settings
    //
    ··· SCON0······ = 0x50;··// UART receiver enabled
    //
    // Initialize SPI port
    //
    ··· SPI0CFG···· = 0x47;··// SPI set to Master Mode, CPHA=0, CPOL=0
    ··· SPI0CN····· = 0x03;··// SPI enabled
    ··· SPI0CKR···· = 0xff;··// SPI clock rate set to ~102KHz
    //
    // Initialize Interrupt settings
    //
    ··· IE········· = 0x30;··// Enable UART and Timer2 (RTI) interrupts
    ·EIE1······· = 0x10;··// pca interrupt

    }
    //
    //
    // Interrupt Service Routines
    //
    //
    //
    // RTI_ISR
    //
    //
    // Timer2 is the RTI generator
    //
    void RTI_ISR (void) interrupt 5 using 1
    {
    ··
    ·if (timer) --timer;
    ·if (tracking_update) --tracking_update;
    ·if (heading_update) --heading_update;
    ·TF2H = 0;·······// clear interrupt flag
    }
    //
    // UART ISR
    //
    //
    // Here we quickly get the data from the hardware buffer and put it into a storage
    // for retrieval by the command processor.
    //
    void UART_ISR (void) interrupt 4 using 3
    {
    if (TI0) {
    ·TI0 = 0;
    ·B_Txstat = 0;
    ·}
    else {
    ·sbuff = SBUF0;·······// Transfer data from hardware buffer to software buffer
    ··B_proc_cmd = 1;
    ·RI0 = 0;········// Reset Rx interrupt flag
    ·}
    }
  • freq42freq42 Posts: 18
    edited 2004-09-26 13:43
    OK cwolff
    ····I'll post·my final code Four the V2X. I'm not shure·if it will work on·the V2Xe do to the only two listed in my book are the V2X & V2XG. The V2XG uses mechanical gimbals to minimize the effect of tiltin the compass applications.
    After looking over the info four your compass I can see one of your problems
    The pins are different this is the link four the V2X book http://www.jameco.com/wcsstore/Jameco/Products/ProdDS/126703.PDF
    The setup I use dus not look the same four yours. When I get back from Alabama ill look over it sum moor and try to help the best I can.
    ·
    '
    [noparse][[/noparse] I/O Definitions ]
    Lcd············ PIN···· 0······················ ' serial comm to LCD
    Slct··········· PIN···· 2······················ ' select signal
    SDO············ PIN···· 3······················ ' serial data out
    SClk··········· PIN···· 4······················ ' clock signal
    Rst············ PIN···· 5······················ ' reset signal

    '
    [noparse][[/noparse] Constants ]
    ' SIM command bytes
    CtrlA·········· CON···· $01···················· ' Clear command
    CtrlB·········· CON···· $02···················· ' blank cursor
    CtrlD·········· CON···· $04···················· ' configuration prefix
    CtrlI·········· CON···· $09···················· ' forward
    CtrlJ·········· CON···· $0A···················· ' linefeed
    CtrlK·········· CON···· $0B···················· ' vertical tab
    CtrlL·········· CON···· $0C···················· ' clear
    CtrlM·········· CON···· $0D···················· ' CR
    CtrlN·········· CON···· $0E···················· ' blank cursor
    CtrlO·········· CON···· $0F···················· ' block cursor
    CtrlP·········· CON···· $10···················· ' home
    CtrlQ·········· CON···· $11···················· ' underline
    CtrlR·········· CON···· $12···················· ' underline blink
    CtrlS·········· CON···· $13···················· ' blank (does not clear)
    CtrlT·········· CON···· $14···················· ' set descenders
    CtrlU·········· CON···· $15···················· ' clear descenders
    CtrlX·········· CON···· $18···················· ' set single line
    DataEn········· CON···· $FE···················· ' next byte is data
    CtrlEn········· CON···· $FF···················· ' next byte is control

    #SELECT $STAMP
    · #CASE BS2, BS2E, BS2PE
    ··· T1200······ CON···· 813
    ··· T2400······ CON···· 396
    ··· T4800······ CON···· 188
    ··· T9600······ CON···· 84
    ··· T19K2······ CON···· 32
    ··· T38K4······ CON···· 6
    · #CASE BS2SX, BS2P
    ··· T1200······ CON···· 2063
    ··· T2400······ CON···· 1021
    ··· T4800······ CON···· 500
    ··· T9600······ CON···· 240
    ··· T19K2······ CON···· 110
    ··· T38K4······ CON···· 45
    #ENDSELECT
    Inverted······· CON···· $4000
    Open··········· CON···· $8000
    LcdBaud········ CON···· T9600 + Inverted

    '
    [noparse][[/noparse] Variables ]
    gps············ VAR···· Word
    idx············ VAR···· Word
    time··········· VAR···· Word
    hdng··········· VAR···· Word
    hdng2·········· VAR···· Word
    pntr··········· VAR···· Nib
    char··········· VAR···· Byte

    '
    [noparse][[/noparse] EEPROM Data ]
    HdgStr· DATA··· "N NEE SES SWW NW"

    '
    [noparse][[/noparse] Initialization ]
    Reset:
    · PAUSE 100···························· ' let LCD intialize
    · SEROUT Lcd, LcdBaud, [noparse][[/noparse]CtrlD, "Q"]···· ' set SIM for 20x4 display
    · PAUSE 10····························· ' let LCD clear
    Compass_Init:
    · HIGH SClk
    · HIGH Slct····· 'make sure this is high.
    · LOW Rst······· 'lower reset pin.
    · PAUSE 15······ 'wait 15 ms.
    · HIGH Rst······ 'raise reset pin.
    · PAUSE 200····· 'wait a bit.

    '
    [noparse][[/noparse] Program Code ]
    Main:
    · DO
    ··· GOSUB Get_Compass
    ··· GOSUB Show_Compass
    ··· GOSUB show_heading2
    ··· GOSUB Show_Azimuth
    ··· PAUSE 500
    · LOOP
    · END

    '
    [noparse][[/noparse] Subroutines ]
    Get_Compass:
    · LOW Slct····························· ' start compass
    · PAUSE 200···························· ' wait for heading
    · hdng = 0····························· ' clear old value
    · SHIFTIN SDO, SClk, MSBPRE, [noparse][[/noparse]hdng\16]· ' get new value
    · HIGH sclk···························· 'reset pins.
    · HIGH Slct
    · RETURN

    Show_Compass:
    · SEROUT Lcd, LcdBaud, [noparse][[/noparse]CtrlP]········· ' home
    · PAUSE 5
    · SEROUT Lcd, LcdBaud, [noparse][[/noparse]"Heading: ", DEC3 hdng, 223]
    · RETURN

    Show_Heading2:
    · LOOKDOWN hdng, <=[noparse][[/noparse]22,67,112,157,202,247,292,337,360], pntr
    · pntr = pntr // 8 * 2
    · FOR idx = 0 TO 1
    ··· READ (HdgStr + pntr + idx), char
    ··· SEROUT Lcd, LcdBaud, [noparse][[/noparse]char]
    · NEXT
    · 'RETURN
    ·
  • cwolffcwolff Posts: 24
    edited 2004-09-27 18:07
    Julian Benton over at PNI was kind enough to share this sample code for interfacing a V2XE with a BS2p.· I'll try it out tonight and let you know if it works!

    '{$Stamp BS2p}··········· 'Stamp Directive (specifies BS2P)
    '*********************************************************************
    '·· OEM Example Program for the Basic Stamp 2p uProcessor to
    '·· interface with a PNI Corporation V2Xe 2 Axis Compass Module.
    '·· This program shows how to get the Heading from the V2Xe.
    '·· Copyright 20Dec2003, PNI Corporation
    '·· Written by Julian Benton, Applications Engineer
    '·· Contact: jbenton@pnicorp.com , 707-566-2260 x356
    '*********************************************************************
    'Declare Lines
    SYNC····· CON 5··········· 'SYNC is pin 5
    SSNOT····· CON 7··········· 'SSNOT is pin 7
    MOSI····· CON 8··········· 'MOSI is pin 8
    MISO····· CON 9··········· 'MISO is pin 9
    SCLK····· CON 10········ 'SCLK is pin 10
    'Declare Global Constants for Command Datagrams
    Flag··········· CON·· $AA····· 'Defines Sync Flag which is the first byte of any command
    GetModInfo········ CON·· $1····· 'Defines the frame type that queries the V2Xe for module information
    ModInfoResp····· CON·· $2····· 'Defines the response frame type to command GetModInfo
    SetDataComponents·· CON·· $3····· 'Defines the frame type for the data components to be sent back
    ·· XRaw········ CON·· $1····· 'Defines the Component ID for X sensor RAW Data
    ·· YRaw········ CON·· $2····· 'Defines the Component ID for Y sensor RAW Data
    ·· Heading····· CON·· $5····· 'Defines the Component ID for Heading
    ·· Mag········ CON·· $6····· 'Defines the Component ID for Magnetude
    ·· Dist········ CON·· $8····· 'Defines the Component ID for the distortion flag
    ·· CalStatus····· CON·· $9····· 'Defines the Component ID for calibration status
    SaveConfig········ CON·· $9····· 'Defines the SaveConfig frame type
    GetData········ CON·· $4····· 'Defines the frame type which queries the V2Xe for data components
    DataResp········ CON·· $5····· 'Defines the response to command GetData frame type
    Term··········· CON·· $00····· 'Defines Terminator which is the last byte of any command

    'Declare Variables for Response Datagrams
    FlagIn········ VAR·· Byte····· 'Defines Sync Flag in the response Datagram
    FrameIn········ VAR·· Byte····· 'Defines the Frame Type in the response Datagram
    CountIn········ VAR·· Byte····· 'Defines the number of components in the response Datagram
    XRawIn········ VAR·· Byte····· 'Defines the XRaw ID in the response Datagram
    XRawVal········ VAR·· Word(2)·· 'Defines the XRaw value array in the response Datagram
    YRawIn········ VAR·· Byte····· 'Defines the YRaw ID in the response Datagram
    YRawVal········ VAR·· Word(2)·· 'Defines the YRaw value array in the response Datagram
    HeadingIn········ VAR·· Byte····· 'Defines the Heading ID in the response Datagram
    HeadingVAL········ VAR·· Byte(4)·· 'Defines the Heading value array
    CompHeading····· VAR·· Word····· 'Defines the Heading
    Exponent········ VAR·· Byte····· 'Defines value for Heading calculation
    TermIn········ VAR·· Byte····· 'Defines the Terminator of the resonse Datagram

    'Interface with the V2Xe
    ·· HIGH SSNOT
    ·· LOW·· SSNOT·············· 'Enable SPI Port
    'Set the data componets to be read from the V2Xe (Heading and Magnitude)
    ·· LOW SYNC
    ·· PULSOUT SYNC,2··········· 'Not required
    ·· SHIFTOUT MOSI,SCLK,MSBFIRST,[noparse][[/noparse]Flag,SetDataComponents,$1,Heading,Term]····· 'Set Heading as output
    ·· PAUSE 1
    Begin:
    ·· SHIFTOUT MOSI,SCLK,MSBFIRST,[noparse][[/noparse]Flag,GetData,Term]················· 'Request output (Heading)
    ·· Loop:
    ····· SHIFTIN MISO,SCLK,MSBPRE,[noparse][[/noparse]FlagIn]······················· 'Look for Sync Flag
    ········ IF FlagIn <> $AA THEN Loop
    ·· SHIFTIN MISO,SCLK,MSBPRE,[noparse][[/noparse]FrameIn,CountIn,HeadingIn,HeadingVal(0),HeadingVal(1),HeadingVal(2),HeadingVal(3),TermIn]····· 'Shift in data (Heading)

    'IEEE 32 bit floating point to scaled integer
    'Integer will be scaled * 8 (i.e. 1 = 1/8, 2 = 1/4, 3 = 3/8, 4 = 1/2 ... 8 = 1.0 )
    'IEEE32 format:
    ·· '31............24...23............16...15.............8...7..............0
    ·· 'S E E E· E E E E·· E F F F· F F F F·· F F F F· F F F F·· F F F F· F F F F
    ···· 'HeadingVal(0)····· HeadingVal(1)····· HeadingVal(2)····· HeadingVal(3)·· //For Compass Heading
    ···· 'MagVal(0)········· MagVal(1)········· MagVal(2)········· MagVal(3)····· //For Magnitude
    ·· 'S = Sign
    ·· 'E = Exponent
    ·· 'F = Mantisa or Binary Fraction
    ·· 'Number = 1.F * 2^(E-127)
    ·· 'The code below will assume Sign = 0 (number is positive) for all headings
    ·· 'if the heading is less than 1 degree or zero (the IEEE32 version of zero)
    ·· 'IMPORTANT!!! This code truncates to the nearest decimal instead of rounding.
    ·· HeadingVal(0) = HeadingVal(0) * 2··········· 'Shift Exponent
    ·· IF HeadingVal(1) < 128 THEN Step1
    ····· HeadingVal(0) = HeadingVal(0) + 1
    ·· Step1:
    ····· Exponent = HeadingVal(0)
    ·· Step2:
    ····· IF Exponent > 126 THEN Step3··········· 'Zero Test
    ····· CompHeading = 0
    ·· GOTO Done
    ·· Step3:
    ····· CompHeading = 1
    ·· Loop2:·························· 'Main loop to extract the Heading integer information
    ····· IF Exponent = 127 THEN Done
    ····· CompHeading = CompHeading * 2
    ····· HeadingVal(1) = HeadingVal(1) * 2
    ····· IF HeadingVal(1) < 128 THEN Step4
    ····· CompHeading = CompHeading + 1
    ····· Step4:
    ········ IF HeadingVal(2) < 128 THEN Step5
    ········ HeadingVal(1) = HeadingVal(1) + 1
    ····· Step5:
    ········ HeadingVal(2) = HeadingVal(2) * 2
    ········ Exponent = Exponent - 1
    ·· GOTO Loop2
    ·· Done:

    'Display Heading
    ····· DEBUG "Heading: ",DEC CompHeading, CR,10
    ·· Pause 500
    ·· GOTO Begin·························· 'Repeat
    ·· High SSNOT·························· 'Disable SPI Port
    END
  • cwolffcwolff Posts: 24
    edited 2004-09-27 18:10

    Jon,

    Any suggestions on the Float32 function?· Thank you.



    Mr. Wolff,

    Thank you for your interest in PNI Products. For testing in house I have a used the Basic Stamp 2p to control the V2Xe. Attached you will find a number of examples which should help you out. I do not have much experience with programming the Basic Stamp, and as a result I have not been able to get the Compass example working correctly. I did ask around and received a few hints on getting the Float32 brought into the Basic Stamp in a way that it can be used. I have attached both my non working example along with the "hints". Hopefully, this will be helpful.

    Once I have some more time I hope to get all of the examples working and posted to our website for others, such as yourself to use.

    Please let me know if you have any questions.

    Julian Benton

    Applications Engineer

    jbenton@pnicorp.com

    (707) 566-2260 ext. 356

  • Tracy AllenTracy Allen Posts: 6,658
    edited 2004-09-28 18:00
    >> Any suggestions on the Float32 function?· Thank you.

    There was a thread on this topic back on the old Yahoo groups Stamp board last June 8th-10th . (subject: Converting IEEE 32 bit floating point to scaled integer). I think we come up with some nifty compact code there that reduced the conversion from IEEE32 to three lines of PBASIC (for the V2XE ), plus some optional error checking.

    groups.yahoo.com/group/basicstamps/message/44991
    groups.yahoo.com/group/basicstamps/message/45030
    groups.yahoo.com/group/basicstamps/message/45041

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com
  • freq42freq42 Posts: 18
    edited 2004-10-02 15:03
    attachment.php?attachmentid=73582
    780 x 266 - 9K
Sign In or Register to comment.