Shop OBEX P1 Docs P2 Docs Learn Events
Reading the Tri-Axis Accelerometer using SX/B and SX28 — Parallax Forums

Reading the Tri-Axis Accelerometer using SX/B and SX28

jbrierleyjbrierley Posts: 9
edited 2007-11-25 20:19 in General Discussion
Hi, everyone.· I've been doing some work to do a basic g-meter using the Parallax tri-axis accelerometer and a serial LCD module.· When I run the code, I get the expected reference count (around about 2048), but if I hit the reset button (sometimes a few times), I start getting a reference count around 5120, which is obviously not right.· I think it might be something to do with the clock frequency, since it seems stable while it's running using the SX-Key.· As soon as I put an external resonator on it, though, it seems to have the problem (although sometimes it works then as well).· Very strange, and it's driving me nuts!· I've tried both the 4 MHz and 50 MHz resonators and the problem is the same.· I've also tried the 4 MHz internal clock.

Could anyone have a look at my code for reading the accelerometer and see if they can see if anything is wrong?· I've extracted just the reference count code so it's clearer.· In reality there's code for reading the axis counts as well.· It's my first program for the SX (just got the kit last week), so it might be a bit messy.

Get_Acc:
  LOW CS
  ' Prod the accelerometer and select the reference voltage count register
  SHIFTOUT Dio, Clk, MSBFIRST, %11\2
  SHIFTOUT Dio, Clk, MSBFIRST, Vef\3  ' select vref register
 
  ' Null bit and the high four bits of the ADC reading into the low nibble of the byte variable rvCount1
  SHIFTIN DIO, CLK, MSBPOST, rvCount1\5
 
  ' Get the rest of the ADC reading into rvCount2 byte variable
  SHIFTIN DIO, CLK, MSBPOST, rvCount2\8

  HIGH CS
  PAUSE 1
  PUT @rvCount, rvCount2, RvCount1 ' Put the 12-bit reference count value into a WORD variable (rvCount)
 RETURN


Any ideas?

Thanks everone,
Jon

Comments

  • BeanBean Posts: 8,129
    edited 2007-11-19 01:52
    Jon,
    We need to see what you have on the DEVICE line for each resonator.
    It's always best to post the entire code.

    Bean

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    www.iElectronicDesigns.com

    ·
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-19 01:59
    Sorry.· Here's the various ones:

    When using the 4 MHz resonator:

    DEVICE········· SX28, OSCXT1, TURBO, STACKX, OPTIONX
    FREQ··········· 4_000_000

    When using the 50 MHz resonator:

    DEVICE········· SX28, OSCHS1, TURBO, STACKX, OPTIONX
    FREQ··········· 50_000_000

    I've actually tried various combinations for the external resonators, but they all seem to suffer the same problem.

    Regards,
    Jon
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-19 02:04
    Sorry it's such a mess (which is why I didn't post the whole thing before - I've been trying different things), but here's the whole code:
    ' =========================================================================
    '
    '   File...... TEMPLATE.SXB
    '   Purpose... SX/B Programming Template
    '   Author.... 
    '   E-mail.... 
    '   Started...
    '   Updated... 05 JUL 2006
    '
    ' =========================================================================
    ' -------------------------------------------------------------------------
    ' Program Description
    ' -------------------------------------------------------------------------
    
    ' -------------------------------------------------------------------------
    ' Device Settings
    ' -------------------------------------------------------------------------
    'DEVICE          SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
    'FREQ            4_000_000
    DEVICE          SX28, OSCXT1, TURBO, STACKX, OPTIONX
    FREQ            4_000_000
    'DEVICE          SX28, OSCHS2, TURBO, STACKX, OPTIONX
    'FREQ            4_000_000
    ID              "SXB 1.50"
    
    ' -------------------------------------------------------------------------
    ' IO Pins
    ' -------------------------------------------------------------------------
    LcdTx           PIN     RA.1                    ' LCD serial connection
    Dio             PIN     RB.1                      ' data to/from module
    Clk             PIN     RB.0                      ' clock output
    CS              PIN     RB.2                      ' active-low chip select
    
    ' -------------------------------------------------------------------------
    ' Constants
    ' -------------------------------------------------------------------------
    LcdBaud         CON     "T19200"                ' or T2400, or T9600
    LcdLF           CON     $0A                     ' move cursor down 1 line
    LcdCls          CON     $0C                     ' clear LCD (need 5 ms delay)
    LcdCR           CON     $0D                     ' move pos 0 of next line
    LcdBLon         CON     $11                     ' backlight on
    LcdOn1          CON     $16                     ' LCD on; no crsr, no blink
    LcdLine1        CON     $80                     ' move to line 1, column 0
    LcdLine2        CON     $94                     ' move to line 2, column 0
    XAxis           CON     0                       ' adc channels
    YAxis           CON     1
    ZAxis           CON     2
    VRef            CON     3
    gfcnv  CON $3852
    ' -------------------------------------------------------------------------
    ' Variables
    ' -------------------------------------------------------------------------
    tmpB3           VAR     Byte
    tmpW1           VAR     Word
    axis VAR BYTE
    rvCount VAR WORD
    rvCount1 VAR BYTE
    rvCount2 VAR BYTE
    axCount VAR WorD
    axCount1 VAR BYTE
    axCount2 VAR BYTE
    value VAR WORD
    char VAR BYTE
    lcd1 VAR WORD
    ndex VAR byte
    sgn var BYTE
    
    ' -------------------------------------------------------------------------
      INTERRUPT
    ' -------------------------------------------------------------------------
    ISR_Start:
      ' ISR code here
    ISR_Exit:
      RETURNINT ' {cycles}                                 
    
    ' =========================================================================
      PROGRAM Start
    ' =========================================================================
    
    ' -------------------------------------------------------------------------
    ' Subroutine Declarations
    ' -------------------------------------------------------------------------
    DELAY           SUB     1, 2                    ' delay in milliseconds
    LCD_OUT         SUB     1, 2                    ' byte or string to LCD
    CLEAR_LCD       SUB     0                       ' clear LCD, BL is on
    Get_H48C SUB 0   ' accelerometer reading
    WRITELCDCHAR    SUB     1                       ' delay in milliseconds
    WriteByte SUB 1
    ' -------------------------------------------------------------------------
    ' Program Code
    ' -------------------------------------------------------------------------
    Start:
      ' initialization code here
    PAUSE 100
      CLEAR_LCD
      LCD_OUT LcdBLon
    Again:
      LCD_OUT LcdLine1
      ndex = 0
      LCD_OUT "R="
      FOR axis = XAxis TO Zaxis
        ndex = ndex + 1
        GOSUB Get_H48C
        if rvCount > 4096 then
     if ndex = 1 then
             value = rvCount
          WRITELCDCHAR 0
      LCD_OUT LcdLine2
      LCD_OUT "--ERROR--"
     endif
        else
          if ndex = 1 then
              value = rvCount
        WRITELCDCHAR 0
           LCD_OUT ", X="
          endif
          if ndex = 2 then
            LCD_OUT LcdLine2
     LCD_OUT "Y="
          endif
          if ndex = 3 then
         LCD_OUT ", Z="
          endif
          value = axCount
          WRITELCDCHAR 1
        endif
      NEXT 
      delay 250
      ' main code here
      GOTO Again
    
    ' -------------------------------------------------------------------------
    ' Subroutine Code
    ' -------------------------------------------------------------------------
    Get_H48C:
      LOW CS
      SHIFTOUT Dio, Clk, MSBFIRST, %11\2
      SHIFTOUT Dio, Clk, MSBFIRST, Vef\3  ' select vref register
      SHIFTIN DIO, CLK, MSBPOST, rvCount1\5
      SHIFTIN DIO, CLK, MSBPOST, rvCount2\8
      HIGH CS
      PAUSE 1
      LOW CS
      SHIFTOUT Dio, Clk, MSBFIRST, %11\2
      SHIFTOUT Dio, Clk, MSBFIRST, axis\3  ' select axis
      SHIFTIN DIO, CLK, MSBPOST, axCount1\5
      SHIFTIN DIO, CLK, MSBPOST, axCount2\8
      HIGH CS
      PUT @rvCount, rvCount2, RvCount1 ' Put the 12-bit reference value into a WORD variable
      PUT @axCount, axCount2, axCount1 ' Put the 12-bit axis value into a WORD variable
      '  Convert the axis reading to a g-force
      '  sgn is 0 for positive, 1 for negative
      if axCount >= rvCount then
        axCount = axCount - rvCount
        axCount = axCount ** gfcnv
        sgn = 0
      else
        axCount = rvCount - axCount
        axCount = axCount ** gfcnv
        sgn = 1
      endif
      RETURN
    WRITELCDCHAR:
    rvCount1 = __PARAM1
    if sgn = 1 then
      LCD_OUT "-"
    else
      LCD_OUT "+"
    endif
    tmpW1 = value / 1000
    GET @tmpW1, axCount2, axCount1
    if tmpW1 > 0 then
      WriteByte axCount2
    endif
    tmpW1 = value // 1000
    tmpW1 = tmpW1 / 100
    GET @tmpW1, axCount2, axCount1
    WriteByte axCount2
    if rvCount1 > 0 then
      LCD_OUT "."
    endif
    tmpW1 = value // 1000
    tmpW1 = tmpW1 // 100
    tmpW1 = tmpW1 / 10
    GET @tmpW1, axCount2, axCount1
    WriteByte axCount2
    tmpW1 = value // 1000
    tmpW1 = tmpW1 // 100
    tmpW1 = tmpW1 // 10
    GET @tmpW1, axCount2, axCount1
    WriteByte axCount2
    Return
    WriteByte:
    axCount1 = __PARAM1
    'break
    if axCount1 > 9 then
     char = "-"
    else
     Read TheData + axCount1, char
    endif
    LCD_OUT char
    RETURN
    ' Use: DELAY ms
    ' -- 'ms' is delay in milliseconds, 1 - 65535
    DELAY:
      IF __PARAMCNT = 1 THEN
        tmpW1 = __PARAM1                            ' save byte value
      ELSE
        tmpW1 = __WPARAM12                          ' save word value
      ENDIF
      PAUSE tmpW1
      RETURN
    LCD_OUT:
      axCount1 = __PARAM1                              ' byte or string offset
      IF __PARAMCNT = 2 THEN                        ' string specified?
        axCount2 = __PARAM2                            '   yes, save base
        DO
          READ axCount2 + axCount1, tmpB3                 ' read a character
          IF tmpB3 = 0 THEN EXIT                    ' if 0, string complete
          SEROUT LcdTx, LcdBaud, tmpB3              ' send the byte
          INC axCount1                                 ' point to next character
          axCount2 = axCount2 + Z                         ' update base on overflow
        LOOP
      ELSE
        SEROUT LcdTx, LcdBaud, axCount1                ' send the byte
      ENDIF
      RETURN
    ' -------------------------------------------------------------------------
    ' Use: CLEAR_LCD
    ' -- clears the LCD and activates the backlight
    ' -- removes cursor and blinking block
    CLEAR_LCD:
      LCD_OUT LcdBLon                               ' backlight on
      LCD_OUT LcdOn1                                ' no cursor or blink
      LCD_OUT LcdCls                                ' clear the LCD
      DELAY 5
      RETURN
    
    ' =========================================================================
    ' User Data
    ' =========================================================================
    TheData:
    DATA "0123456789"
     
    

    ·
  • JDOhioJDOhio Posts: 72
    edited 2007-11-19 02:20
    I noticed that the Accelerometer is a 3.3 volt device. Are you running the SX at 3.3 volts or 5 volts? If you are running it at 5 volts, how are you interfacing the Accelerometer I/O? Could the differences in supply voltage account for odd readings?

    I see that after receiving data from the Accelerometer, the code moves it to a WORD in preparation for displaying it on the LCD. Is the data valid before moving? You might want to validate that the data arrives from the Accelerometer before attempting to display the data. In this manner, you can isolate the error to either the data transmission, or the code that does the displaying.

    Joe

    Post Edited (JDOhio) : 11/19/2007 2:41:26 AM GMT
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-19 02:36
    It's got an on-board regulator to supply the 3.3V from a 5V supply.· I'm connecting it according to the docs on the Parallax page (http://www.parallax.com/Portals/0/Downloads/docs/prod/acc/HitachiH48C3AxisAccelerometer.pdf).· They connect +5V to Vdd (pin 6).· That's where·most of the code came from.· It's BS2 code, so I had to modify it, naturally.· It's just very strange - it works perfectly...· but only under certain conditions:· SX Key and no external oscillator plugged in.· As soon as you remove the SX key and plug in an external oscillator (or use the built-in one), it gets the wrong numbers.

    I'm using an SX Tech Board for prototyping it, just so you have all the information.

    I can't tell if it's valid.· If I run it to debug, it works fine.· If I hit reset (which stops the debugging), that's when the problem occurs (as well as when I disconnect the SX-Key).· It runs, just with the wrong numbers.

    Thanks,
    Jon

    Post Edited (jbrierley) : 11/19/2007 2:41:51 AM GMT
  • JDOhioJDOhio Posts: 72
    edited 2007-11-19 02:48
    Jon,

    I was looking through the reference document and it looks like it does the voltage interfacing for you. That is probably not an issue. And, my suggestion of stepping through to verify the data transfer won't work since you are seeing a difference with and without the SX Key.

    If the device and the SX operate correctly with the SX key, then it would seem like the difference would be the oscillator as you suspect. That would affect all of the calculations the compiler makes for the timing of the SHIFTxx commands. Can you verify that the oscillator matches what the code says - i.e., are you installing a 4 MHz oscillator?

    Joe
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-19 02:54
    I'm pretty sure - I think!· I bought two SX chips and two resonators came with them.· One is definitely the 50 MHz one (the number printed on it matches the parallax web site).· The 4 MHz one, however, has a code on it that doesn't match the parallax one.· The code is 400G-625.· (I think it's a "G").· The resonator datasheet didn't clear that up at all (it's not terribly helpful)·so I emailed parallax support earlier this afternoon to find out for sure.· Regardless, I've tried it with both (changing the device line), and it's the same story.

    Thanks,
    Jon
  • JDOhioJDOhio Posts: 72
    edited 2007-11-19 03:08
    Jon,

    In the line where you specify options for DEVICE, have you tried using

    DEVICE SX28, OSCXT1


    For my SX-48 project, I used this syntax for setting the frequency:

    FREQ 4000000

    I know I'm starting to reach here.

    Another idea is to use an oscilloscope to look at the data as it is transferred. In that way, you could compare the transfer with and without the SX Key. Without an oscilloscope, you might have to add some code to display various values of variables on the LCD. For example, is it possible to display the data before the conversions for display? Could you rotate through the bits, add $30, and display each bit? This would be another way of looking at differences with and without the SX Key.

    Joe
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-19 03:18
    I just tried that, Joe. If I remove the rest of the line (after the OSCXT1), I get nothing (once I cycle the power).

    I'll try your other suggestions. I'll try writing the bits to the display first and make sure that the byte and word variables match. If they do, I'll dig out the oscilloscope.

    Thanks for trying, Joe, and I'll update once I've tried it.

    Regards,
    Jon
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-23 01:14
    Update:··Hi, Joe:· I did what you suggested and set it to output the binary 12 bits it's getting from the ShiftIn code.· The Binary output was bouncing around just like the decimal value was.· So I dug out the oscilloscope and started watching what was happening.· The signal was nice and steady (no bouncing bits in the first nibble)·and matched what the docs for the ADC was saying (see attachment).

    I think what's happening is that for some reason when reset it's counting the pause while the reading is being taken as a bit in the communications packet.· If I set it to read it as a communications bit (aka two null bits rather than one), it gets the expected VRef value (2048).· I guess that works and I'll go with it for now, but I hope it won't all of a sudden start doing it properly, because then it would read wrong again!

    Thanks for the answers.· Any other ideas about what it might be occur to you?

    Thanks,
    Jon
    752 x 453 - 84K
  • JDOhioJDOhio Posts: 72
    edited 2007-11-24 13:58
    The only thing that I see, and this may be small, is that one example in the documentation shows leading zeros in the request. I'd be curious to know if there is a change in behavior if you had the SX send 8 bits in the request (five leading zeros, the start bit, mode bit, and three channel bits). Also, if you placed all of these into a single byte, you could make one SHIFTIN call.

    Joe
  • jbrierleyjbrierley Posts: 9
    edited 2007-11-25 20:19
    I just tried it, Joe.· It doesn't seem to make a difference.· I wish I knew what was going on.· By reading two null bits it works most of the time, but occasionally it switches to reading garbage (which I'm sure if I went back to one null bit would then work).· So I hit the reset button and it's back to running "properly" again.· Basically...· it's inconsistent.· Maybe a timing issue...· I don't know.· I'm out of ideas.
Sign In or Register to comment.