The Godfather talking
You think I am funny guy huh?
Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
December 10, 2016, 04:00:59 04:00


Login with username, password and session length


Pages: [1]
Print
Author Topic: Accelerometer Tutorial using an include file  (Read 1589 times)
0 Members and 1 Guest are viewing this topic.
Jayridium
Inactive

Offline Offline

Posts: 4

Thank You
-Given: 1
-Receive: 4


« on: December 31, 2012, 07:30:34 19:30 »

Hi and happy new year,

 This is my first post in the forum, but I've been lurking around here for a couple of years reading and learning from you guys before I took the plunge to join and share some knowledge. I thought as a first post I'd share a useful little bit of code I wrote to use as an include with proton to really take all the hard work out of using accelerometers with proton.

  At this point it is only fair to pass credit onto Les at myamicus.co.uk who wrote a good tutorial and sample code currently at http://www.myamicus.co.uk/content.php?270-MMA7260-Accelerometer-Interface - that I modified to make it into an include that can easily be called upon by any subsequent programs.

Code:
'-------------------------------------------------------------------- 
'  Variables  +   Declarations
'-------------------------------------------------------------------- 
'device = 18f4550      'device identifier to allow test compilations
'only assigned as the default chip in proton compiler doesn't have
'enough ram to cope with this program
'--------------------------------------------------------------------
 'The following variables MUST be assigned values in the main program
    Dim Sensitivity As Byte      'Accelerometer Max G-force
    Dim Channel_X As Byte        'ADC Channel to read X Axis from
    Dim Channel_Y As Byte        'ADC Channel to read Y Axis from
    Dim Channel_Z As Byte        'ADC Channel to read Z Axis from
    Dim ADC_Sample_Width_Bits As Word   'How Many Bits Resolution ADC is set at
    Dim VDD As Float             'VDD Voltage used in system
 '--------------------------------------------------------------------   
    Dim Bandwidth_Calc As Word
    Dim ADC_Increments As Dword   'To be calculate as 2 to the power(ADC_Resolution)
   
    let Bandwidth_Calc = ADC_Sample_Width_Bits
    let ADC_Increments = 1  'make it 1 so as we can double it again and again
    'as part of the process of converting a decimal number into a binary power
    'ie ADC_Sample_Width_Bits = 8 = binary 11111111 = 255 = ((1 * (2*2*2*2*2*2*2*2)-1)
    While Bandwidth_Calc > 0 ' while loop
     let ADC_Increments = ADC_Increments * 2 'double ADC_Increments for every bit
     Dec  Bandwidth_Calc                     'of ADC_Sample_Width_Bits
     Wend
     let  ADC_Increments = ADC_Increments - 1   ' minus one to represent the Right Most Bit being a 1 not a 2
  '--------------------------------------------------------------------------------------------------   
    Symbol AD_Inc_Factor = VDD / ADC_Increments     ' ADC to voltage conversion (VDD / ADC resolution)
    Symbol cDegreeConversion = 180.0 / 3.14159265 ' Conversion from radians to degrees
   
    Dim Resultant As Float                  ' Holds the result of the multiple sqr
   
    Dim ResultantX As Float                 ' Holds the result of  fGravity_X squared
    Dim ResultantY As Float                 ' Holds the result of  fGravity_Y squared
    Dim ResultantZ As Float                 ' Holds the result of  fGravity_Z squared
   
   
    Dim Square_Temp As Float                  ' Holds the result of the multiple sqr
   
    Dim Volts_Per_G As Float
   
    Dim Angle_X As Byte              ' Holds the inclination angle of the X axis
    Dim Angle_Y As Byte              ' Holds the inclination angle of the Y axis
    Dim Angle_Z As Byte              ' Holds the inclination angle of the Z axis
   
    Dim Gravity_X As Float         ' Holds the result of the X axis g-force calculation
    Dim Gravity_Y As Float         ' Holds the result of the Y axis g-force calculation
    Dim Gravity_Z As Float         ' Holds the result of the Z axis g-force calculation

    Symbol Zero_G_X = 1.57          ' Zero g voltage level for X axis, as measured
    Symbol Zero_G_Y = 1.55          ' Zero g voltage level for Y axis, as measured
    Symbol Zero_G_Z = 1.65          ' Zero g voltage level for Z axis, as measured
     
    Dim X_Force As Word            ' Holds the median filtered result from the ADC
    Dim Y_Force As Word            ' Holds the median filtered result from the ADC
    Dim Z_Force As Word            ' Holds the median filtered result from the ADC
   
    Dim X_Axis_Volts As Float          ' Holds the voltage output from the channel
    Dim Y_Axis_Volts As Float          ' Holds the voltage output from the channel
    Dim Z_Axis_Volts As Float          ' Holds the voltage output from the channel
'
' Variables used by the bubble sort routine
'   
    Dim SortIndex As Byte
    Dim Swap_Occured_Flag As Bit
    Dim Sort_Swap_Temp As Word
    Dim Sort_Result As Sort_Swap_Temp
   
    Symbol ADC_SamplesToTake = 9       ' The amount of samples to take for the bubble sort
    Dim Working_Sample_Array[ADC_SamplesToTake] As Word
                                           
        Declare Adin_Res = ADC_Sample_Width_Bits   ' X-bit result required 
        Declare Adin_Tad = FRC   ' RC OSC chosen           
        Declare Adin_Stime = 50  ' Allow 50us sample time 
       
'--------------------------------------------------------------------
' Read the X output from the accelerometer (Forward-Backward)
'
' Input     : None
' Output    : X_Force holds the filtered result from the ADC
'             X_Axis_Volts holds the voltage output from the channel
' Notes     : None
'-------------------------------------------------------------------- 
ReadChannel_X:
'-------------------------------------------------------------------- 
    For SortIndex = (ADC_SamplesToTake - 1) To 0 Step -1  ' Create a loop for the amount of samples to take
        Working_Sample_Array[SortIndex] = ADIn Channel_X     ' Read the channel into the filter array
         ' Read the value from channel 0 of the ADC and place in variable Var1. 
        DelayUS 2                                       ' A small delay to allow the ADC's capacitor to re-charge
    Next                                                ' Close the loop
    GoSub MedianFilter                                  ' Perform a median filter on the samples
    X_Force = Sort_Result                              ' Transfer the result of the filter
    X_Axis_Volts = X_Force * AD_Inc_Factor                      ' Convert to a voltage
    Return
'--------------------------------------------------------------------
' Read the Y output from the accelerometer (Side to Side)
'
' Input     : None
' Output    : Y_Force holds the filtered result from the ADC
'             Y_Axis_Volts holds the voltage output from the channel
' Notes     : None
'-------------------------------------------------------------------- 
ReadChannel_Y:
'-------------------------------------------------------------------- 
    For SortIndex = (ADC_SamplesToTake - 1) To 0 Step -1  ' Create a loop for the amount of samples to take
        Working_Sample_Array[SortIndex] = ADIn Channel_Y     ' Read the channel into the filter array
        DelayUS 2                                       ' A small delay to allow the ADC's capacitor to re-charge
    Next                                                ' Close the loop
    GoSub MedianFilter                                  ' Perform a median filter on the samples
    Y_Force = Sort_Result                              ' Transfer the result of the filter
    Y_Axis_Volts = Y_Force * AD_Inc_Factor                      ' Convert to a voltage
    Return
'--------------------------------------------------------------------
' Read the Z output from the accelerometer (Up and Down)
'
' Input     : None
' Output    : Z_Force holds the filtered result from the ADC
'             Z_Axis_Volts holds the voltage output from the channel
' Notes     : None
'-------------------------------------------------------------------- 
ReadChannel_Z:
'-------------------------------------------------------------------- 
    For SortIndex = (ADC_SamplesToTake - 1) To 0 Step -1  ' Create a loop for the amount of samples to take
        Working_Sample_Array[SortIndex] = ADIn Channel_Z     ' Read the channel into the filter array
        DelayUS 2                                       ' A small delay to allow the ADC's capacitor to re-charge
    Next                                                ' Close the loop
    GoSub MedianFilter                                  ' Perform a median filter on the samples
    Z_Force = Sort_Result                              ' Transfer the result of the filter
    Z_Axis_Volts = Z_Force * AD_Inc_Factor                      ' Convert to a voltage
    Return
'--------------------------------------------------------------------   
' The main program loop starts here
Main:
'    Set_1_5g()                                          ' Set accelerometer sensitivity
'
' Open the ADC and make AN0, AN1, and AN2 analogue inputs
'   
'    OpenADC'(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_2_TAD, ADC_REF_VDD_VSS, ADC_1ANA & ADC_2ANA & ADC_3ANA)
'
' Display the accelerometer values on the serial terminal
'           
'   While 1 = 1                              ' Create an infinite loop     
        GoSub ReadChannel_X                 ' Read X channel
        GoSub ReadChannel_Y                 ' Read Y channel
        GoSub ReadChannel_Z                 ' Read Z channel
 
'--------------------------------------------------------------------
' Implement a bubble sorting median filter
'
' Input     : Working_Sample_Array holds the values to sort
' Output    : wSortResult holds the median of the values
' Notes     : None

'--------------------------------------------------------------------
   Repeat
        Swap_Occured_Flag = 0                     ' Clear flag that indicates swap.                                 
        SortIndex = 0
        Repeat                                    ' For each cell of the array...
            If Working_Sample_Array[SortIndex] > Working_Sample_Array[SortIndex + 1] Then ' Move larger values up.
                Sort_Swap_Temp = Working_Sample_Array[SortIndex]                        ' ..by swapping them.
                Working_Sample_Array[SortIndex] = Working_Sample_Array[SortIndex + 1]
                Working_Sample_Array[SortIndex + 1] = Sort_Swap_Temp
                Swap_Occured_Flag = 1                                            ' Set bit if swap occurred. 
            EndIf
            Inc SortIndex
        Until SortIndex > ADC_SamplesToTake                             ' Check next cell of the array.
    Until Swap_Occured_Flag = 0
                                                 ' Keep sorting until no more swaps.
         
'-------------------------------------------------------------------- 
MedianFilter:
'--------------------------------------------------------------------
 
    Sort_Result = Working_Sample_Array[ADC_SamplesToTake / 2]           ' Extract the middle (median) value
    Return   

'-------------------------------------------------------------------- 
Calculations:
'-------------------------------------------------------------------- 
    Gravity_X = (X_Axis_Volts - Zero_G_X) / Volts_Per_G
    Gravity_Y = (Y_Axis_Volts - Zero_G_Y) / Volts_Per_G
    Gravity_Z = (Z_Axis_Volts - Zero_G_Z) / Volts_Per_G
        '
        ' Convert the gravity measurements to angles
        '
        ResultantX = Gravity_X * Gravity_X
        ResultantY = Gravity_Y * Gravity_Y
        ResultantZ = Gravity_Z * Gravity_Z
       
        Resultant = Sqr(ResultantX + ResultantY + ResultantZ)
        '
        ' Convert to integer degrees
        '
        Angle_X = (ACos(Gravity_X / Resultant)) * cDegreeConversion
        Angle_Y = (ACos(Gravity_Y / Resultant)) * cDegreeConversion     
        Angle_Z = (ACos(Gravity_Z / Resultant)) * cDegreeConversion

The Code is pretty long winded and very well commented, as is my programming style, so it should be easy enough to follow..... But if anyone has any problems with it I'll happily help. Basically the way I work it is I saved this as accelerometer.inc in the directory with the rest of the other proton includes, then I start the main program by:

Code:
Device = 18F25K20
Include "accelerometer.inc"
'--------------------------------------------------------------------
 'The following variables MUST be assigned values in the main program
    Let Sensitivity = 3     'Accelerometer Max G-force
    Let Channel_X = 0       'ADC Channel to read X Axis from
    Let Channel_Y = 1        'ADC Channel to read Y Axis from
    Let Channel_Z = 2        'ADC Channel to read Z Axis from
    Let ADC_Sample_Width_Bits = 10   'How Many Bits Resolution ADC is set at
    Let VDD = 4.55             'VDD Voltage used in system
 '--------------------------------------------------------------------   
GoTo ReadChannel_X 'calls the subroutine to read the x channel of the accelerometer
While X_Force <> 0
 HSerOut [ Dec X_Force ]
 Wend


Best wishes, and happy new year....

/Jay
Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC