Reading the Tri-Axis Accelerometer using SX/B and SX28
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.
Any ideas?
Thanks everone,
Jon
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
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
·
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
' ========================================================================= ' ' 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"·
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
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
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
Thanks,
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
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
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
Joe