Shop OBEX P1 Docs P2 Docs Learn Events
Question re Hitachi H48C Tri-Axis Accelerometer Module — Parallax Forums

Question re Hitachi H48C Tri-Axis Accelerometer Module

Brian5084Brian5084 Posts: 9
edited 2008-12-03 20:15 in Learn with BlocklyProp
Hello all,

I have just purchased the Hitachi H48C Tri-Axis Accelerometer Module and I am having a bit of trouble programming it.· What I want it to do is change pitch (using the speaker) when tilted x and y and operate the servo according to x-axis input.

Any help would be appreciated.

Thanks
Brian

Comments

  • SRLMSRLM Posts: 5,045
    edited 2008-11-25 21:49
    Have you looked at the accelerometer demo code? It's available on the product page. If I remember right, it repeats a loop three time, once for each axis. You'll probably want to add four more variables: x/y force, and x/y direction. Then, you'll want to figure out how to relate the force to servo pulses, and the same for direction.
  • Brian5084Brian5084 Posts: 9
    edited 2008-11-25 22:36
    Yea, I looked at the code. Unfortunately I'm not very good at programming. I'm not exacly sure how the output from the chip works.
  • SRLMSRLM Posts: 5,045
    edited 2008-11-25 22:56
    You can use the sample code, and just repurpose the varriables given. You'll want to use the gforce variable for the output from the module: just create a couple more variables (such as xForce and yForce) to hold the values. You don't want to use gforce dirrectly, since that is used for each axis (in the loop). You'll want some code like this psuedo code:

    IF loop = x axis
    xForce = gForce

    ELSEIF loop = y axis
    yForce = gForce



    That goes near the end of main, just before the debug. Then, replace the PAUSE 200 just below that with something like this:

    Calculate PULSOUT values
    LOOP 10 times
    --PULSOUT servos
    --Pause 20

    To get a general overview of programming, take a look at "What's a Microcontroller" (in the downloads section of the Parallax website).
  • Brian5084Brian5084 Posts: 9
    edited 2008-11-25 23:02
    Thanks. I'll try that.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2008-11-25 23:45
    Brian -

    Just be sure you don't use the word "loop" since LOOP is a reserved word in PBASIC 2.5. I don't believe that the IDE is case sensitive, thus it sees any form of "loop" the same as LOOP (the PBASIC command).

    I realize what was offered was just pseudo-code, but I didn't want you to be pulling your hair out over nothing.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When all else fails, try inserting a new battery.
  • Brian5084Brian5084 Posts: 9
    edited 2008-11-26 00:04
    Thanks
  • SRLMSRLM Posts: 5,045
    edited 2008-11-26 03:01
    When writing psuedo code, I tend to capitalize commands. Sorry for any confusion.
  • Brian5084Brian5084 Posts: 9
    edited 2008-11-27 01:01
    This is sort of working....the new code is marked as NEW CODE. but its choppy and sounds terrible. I'm trying to make and engine noise.

    Any suggestions?





    Dio PIN 15 ' data to/from module
    Clk PIN 14 ' clock output
    CS PIN 13 ' active-low chip select


    '
    [noparse][[/noparse] Constants ]

    XAxis CON 0 ' adc channels
    YAxis CON 1
    ZAxis CON 2
    VRef CON 3

    Cnt2Mv CON $CE4C ' counts to millivolts
    ' 0.80586 with **
    GfCnv CON $3852 ' g-force conversion
    ' 0.22 with **

    '
    [noparse][[/noparse] Variables ]

    axis VAR Nib ' axis selection
    rvCount VAR Word ' ref voltage adc counts
    axCount VAR Word ' axis voltage adc counts
    mVolts VAR Word ' millivolts
    gForce VAR Word ' axis g-force
    XForce VAR Word
    YForce VAR Word
    dValue VAR Word ' display value
    dPad VAR Nib ' display pad


    '
    [noparse][[/noparse] EEPROM Data ]


    '
    [noparse][[/noparse] Initialization ]

    Reset:
    HIGH CS ' deselect module



    '
    [noparse][[/noparse] Program Code ]

    Main:
    FOR axis = XAxis TO ZAxis ' loop through each axis
    GOSUB Get_H48C ' read vRef & axis counts



    ' calculate g-force
    ' -- "gForce" is signed word

    IF (axCount >= rvCount) THEN
    gForce = (axCount - rvCount) ** GfCnv ' positive g-force
    ELSE
    gForce = -((rvCount - axCount) ** GfCnv) ' negative g-force
    ENDIF
    'NEW CODE
    IF axis = XAxis THEN 'detect output and store gForce into XForce
    XForce = gForce

    ELSEIF axis = YAxis THEN 'detect output and store gForce into YForce
    YForce = gForce
    ENDIF


    FREQOUT 1, 50, (100+(YForce * 100)) 'pitch changes according to Y gForce
    'END NEW CODE


    NEXT
    PAUSE 1
    GOTO Main


    '
    [noparse][[/noparse] Subroutines ]

    ' Reads VRef and selected H48C axis through an MCP3204 ADC
    ' -- pass axis (0 - 2) in "axis"
    ' -- returns reference voltage counts in "rvCount"
    ' -- returns axis voltage counts in "axCounts"

    Get_H48C:
    LOW CS
    SHIFTOUT Dio, Clk, MSBFIRST, [noparse][[/noparse]%11\2, VRef\3] ' select vref register
    SHIFTIN Dio, Clk, MSBPOST, [noparse][[/noparse]rvCount\13] ' read ref voltage counts
    HIGH CS
    PAUSE 1
    LOW CS
    SHIFTOUT Dio, Clk, MSBFIRST, [noparse][[/noparse]%11\2, axis\3] ' select axis
    SHIFTIN Dio, Clk, MSBPOST, [noparse][[/noparse]axCount\13] ' read axis voltage counts
    HIGH CS
    RETURN
  • SRLMSRLM Posts: 5,045
    edited 2008-11-27 04:09
    It sounds bad since you are outputting a short pitch, waiting a little bit, then putting it out again. Also, your maximum change is about 5 "steps" per second, or five different tones. There isn't really a way around this without additional circuitry. You may be able to improve the sound a bit by making the FREQOUT a shorter duration, and adding duplicate FREQOUT statements throughout the program. This will distribute the sound making. You could also go with external hardware to keep the sound going even after the program execution moves on. Something like the SoundPal might work, but I haven't looked at it in a while, so you'll want to make sure.

    Also, if you're posting large amounts of code, please attach your file, rather than pasting it in directly.
  • Brian5084Brian5084 Posts: 9
    edited 2008-11-27 05:02
    Sorry about the code. I came up with a suitable sound. I used the Yforce to adjust the duration of the tones and I added a harmonic. I doesn't sound too bad. Now I need to have the X axis control a servo. Please assume that I have very little programing experience. *smiles*

    Here's what I am trying to do. I have a project for my Engineering and Design class. The assignment was to design a toy. I am making a spaceship that makes engine noises according to Y axis pitch. I have that covered. Now I need the fins to turn with the roll (X axis) using the servo. In other words I want the servo to turn according to the vehicle tipping left or right.

    Thanks in advance for any help.

    Brian
  • SRLMSRLM Posts: 5,045
    edited 2008-11-27 06:18
    Is that a question, or a comment? Assuming it's a question:

    You can move the fins in several different ways. The key is how you want to convert g force to servo position. Probably the best way would be to have two things:

    A filter
    An equation

    The filter smooths out the data so that your servo's aren't constantly wiggling with each little change in tilt, and the equation is to equate the g force to the servo position. Take a look at this link to find out how to smooth data (it's for the propeller, but the same principles apply). If you want to get fancy or just get some ideas, take a look at the PID loop included in one of the stickies at the top of the Stamps in Class forum (found it here) Finally, once you have the data the way that you want it, you can do something like

    pulsewidth = gForce * 100 + servoCenter

    Post Edited (SRLM) : 11/27/2008 6:24:01 AM GMT
  • Brian5084Brian5084 Posts: 9
    edited 2008-12-03 19:00
    I still am having trouble with the servo control.· This is the piece of code:

    ······· IF axis = XAxis THEN··························· 'detect output and store gForce into XForce
    ········ XForce = ((gForce/4) * 1000)· + 750··········· 'convert to values between 500 and 1000

    ······· ELSEIF axis = YAxis THEN······················ 'detect output and store gForce into YForce
    ········ YForce = gForce

    ······· ELSEIF axis = ZAxis THEN
    ········ ZForce = gForce

    ······· ENDIF

    · PULSOUT 14, XForce···································· ' servo control

    I also do not understand the smoothing function described above.

    Sorry to be so incompetent. ·I am new at programming.

    Thanks for your time and patience
  • SRLMSRLM Posts: 5,045
    edited 2008-12-03 20:04
    What do the servos do when you run this code? I can take some guesses, but that's all they are without knowing what the servo is doing.

    One potential problem that I see is that you are not refreshing the servos correctly. A servo needs to have a refresher pulse sent every 20 ms (more or less). So, if your code takes too long or is too fast, that can create problems. If it's too fast, then you can just add a pause statement, and if it's too slow, then you can cut all the x axis stuff (since you're not using it).

    Another problem is that your xForce variable may be more or less than the 1000-2000 range that is ideal. You should have a something that tests and corrects for this. I'm not sure what the gForce capabilities of the accelerometer are, but you are probably using a 'delicate' touch when using it as you are. However, if you were to drop the module into free fall, then gForce is 0 (potentially), and you pulsout 750.

    And no need to worry about asking questions: we all have to learn sometime, and questions are the best indication that you're trying to grasp a topic.
  • Brian5084Brian5084 Posts: 9
    edited 2008-12-03 20:15
    Thanks for your help. I think I have it now! Much obliged!


    Brian
Sign In or Register to comment.