Shop OBEX P1 Docs P2 Docs Learn Events
Ultrasonic sensor to motor vibration -- how to co-vary the two for human navigation? — Parallax Forums

Ultrasonic sensor to motor vibration -- how to co-vary the two for human navigation?

emblemofbeingemblemofbeing Posts: 9
edited 2010-10-04 14:30 in Accessories
Hey everyone :smilewinkgrin:

So I just purchased a BASIC Stamp HomeWork Board today along w/ a Parallax PING))) Ultrasonic distance sensor. I also removed two little motors with de-centered disks from an old PS2 controller ('dualshock' technology, I think its called).

So far, the PING))) is functional, giving a nice read-out of distance to BASIC Stemp Editor, on my laptop.

My question is this: how might I get a motor (or preferably both motors) to continuously vibrate with more intensity as surfaces grow nearer and, conversely, vibrate with less intensity as surfaces are detected as further away?

To give a rough idea of my goal here: I'd like for a human observer to be able to discriminate, say, a tennis ball from a rubix cube from a meter or so away (or whatever the optimal distance for the perceiver). Any info or guidance would be a HUGE help!

Thanks very much, in advance!
--Very tired from reading all day, time to sleep,

John

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-01 08:05
    Basically, you need to vary the speed of the motor(s) to produce different intensities of vibration. You'll need to do some experimentation to produce a scale of motor speed vs. perceived vibration intensity. You'll need some kind of motor controller. Something like this should work with the small motors involved.

    You'd take the distance values from the PING))) code and run them through some kind of formula to get a motor speed that you'd send to the motor controller. The formula would be derived from the experimental data.
  • emblemofbeingemblemofbeing Posts: 9
    edited 2010-10-01 09:02
    Thanks for the outline and tip on the motor controller, Mike!


    Any advice on where to find code for carrying this out? To get started with the fine-tuning of the distance->vibration dynamic, I mean?
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-01 09:47
    No, you wouldn't find any ready-made examples.

    You're going to just have to accumulate some data. The motor controller uses a range of values from 0 to 127 for the speed of the motor. You'll have to try a series of values to see what the vibration feels like and score that, maybe on a scale from 0 to 7 or 0 to 16. Try it with several people and see what variations there may be. The easiest way to record this is to use a spreadsheet. You can then fit a polynomial to the data points you have. Read the documentation for the spreadsheet you'd use for information on curve fitting. There are also articles on the Wikipedia on the subject.

    Once you have some polynomial coefficients (a,b,c), then it's a simple calculation to take a PING))) distance (x), associate the distance range with a range of perceived vibration intensity, and run that through a formula like "y=a*x*x+b*x+c" to get a motor speed value (y) that you can send to the motor controller.
  • emblemofbeingemblemofbeing Posts: 9
    edited 2010-10-01 11:39
    Excellent! Sounds like I have my work cut out for me as far as the motor controller goes. But, until it arrives via mail, I'm thinking, in the mean time:

    I have a servo in front of me (came with the HomeWork Board kit)--what about accelerating/decelerating the rotation of the horn, as a function of distance?

    Would I need to correlate a min/max. distance with a min/max velocity for the horn's rotation (or something like this?), so that the latter varies as a function of the former? Perhaps there is already code available on this?

    (I think this would be a good first step for learning. Then, I suppose the systematic alteration of the horn's direction of rotation would be a more complicated, second step. One step at a time.)
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-01 13:50
    There are all sorts of tutorials that include examples for the use of servos. Click on the Downloads button on Parallax's main web page. You'll see a button for Educational Tutorials. Click on that and you'll see a list of available tutorials. One useful one is Robots with the BoeBot. There is also a useful example for the PING servo bracket.

    Basically, a servo requires a control pulse with a width of 1ms to 2ms repeated about 50 times a second. 1ms moves the servo to one end of its range and 2ms moves it to the other. Read the description of the PULSOUT statement in the Stamp Manual or the Stamp Editor help files. The PULSOUT produces a pulse in units of 2us (with the BS2 Stamp), so 1ms = 500 and 2ms = 1000.

    Say that your PING routine produces a value (X) from 0 to 127. You could move the servo (say on pin 1) through its range with something like this:

    FOR i = 1 to 100 ' allow 2 seconds to move
    PULSOUT 1,(X*500)/128+500
    PAUSE 20 ' 20ms delay
    NEXT i

    X is multiplied by 500 (the range of PULSOUT values), then divided by 128 (the range of PING values supplied). There are only 16 bits for intermediate results, but 500 * 128 is less than 16 bits and operations on the Stamp are unsigned so there shouldn't be a problem with overflow. The 2nd 500 is the lower limit of the PULSOUT value.
  • emblemofbeingemblemofbeing Posts: 9
    edited 2010-10-04 00:10
    Clearly, I recognize that I am lacking some sort of conceptual understanding of the commands used below. What am I doing wrong here?


    -servo lead - pin 1
    -ultrasonic sensor - pin 15

    ' Measure distance with Ping))) sensor and display in cm
    ' Continuous and rapid conversion of measured distance into servo rotation.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}

    ' Conversion constant for room temperature measurements.

    CmConstant CON 2260

    cmDistance VAR Word
    time VAR Word
    horn VAR Word
    i VAR Word

    DO
    PULSOUT 15, 5
    PULSIN 15, 1, time

    cmDistance = cmConstant ** time ' So long as cmDistance stays between 3 - 300,
    horn = (cmDistance*500)/297+500 ' horn remains between 500 - 1000

    IF horn > 1000 THEN horn = 1000 ' Just in case: keeps the standard servo from
    IF horn < 500 THEN horn = 500 ' rotating beyond its intended mechanical limits.

    ' My poor attempt to take Mike Green's advice, definitely something wrong here on my part:

    FOR i = 1 TO 100 ' allow 2 seconds to move
    PULSOUT 1, horn
    PAUSE 20 ' 20ms delay
    NEXT

    DEBUG HOME, DEC3 cmDistance, " centimeters"
    DEBUG CR, DEC3 horn, " = horn"

    LOOP

    As far as I can here, here are some of the problems:
    1) The servo does move some, but not as intended. It stays within a narrow range of rotation, jerking back and forth a bit, each time the sensor takes a measurement.
    2) I believe the servo's FOR...NEXT loop slows down the PING)))'s chirping, so the distance measurements are taken too intermittently.
    3) Thus, it seems to me, there is a problem with my nesting the FOR...NEXT in the DO...LOOP the way I have. But even without the FOR...NEXT loop (just using PULSOUT for pin 1 w/ Duration = horn) the servo movements are still narrow and jerky, as described in problem 1.

    Thanks in advance,
    John
  • Mike GreenMike Green Posts: 23,101
    edited 2010-10-04 07:51
    I think the problem you're running into is that the servos take some time (seconds) to complete their movement, yet you need to continue getting sensor (PING) data while the servo is moving. The Stamps are single threaded microcontrollers and can do only one thing at a time. What to do?

    There are some examples in the "Robotics with the BoeBot" tutorial of combining sensing, decision making, and servo movement. Essentially you set up a single loop with sensing and decision making at the top of the loop and a single servo pulse produced at the bottom of the loop. Instead of the 20ms delay just used for waiting, the delay is shortened or eliminated and the sensing and decision making code provides the additional delay (since that takes some time to do).

    In your case, you may need to do some smoothing of the servo pulse width since it would be calculated every time through the loop and may vary producing servo twitching. One simple thing to do is to keep a servo position variable with the last servo pulse width, add the new calculated pulse width to it, and divide by 2.

    Remember that you can't keep the DEBUG statements in the main loop because they take a substantial period of time to execute (about 1ms per character) and will interfere with the servo.
  • emblemofbeingemblemofbeing Posts: 9
    edited 2010-10-04 11:40
    So, I need to smooth out the servo pulse width by continually averaging together the current and previous servo positions (pulse widths)?
    I'm not sure how to specify a variable which refers to the previous pulse width, and another which refers the newly calculated, present pulse width.


    Also, on the topic of the 'Micro Dual Serial Motor Controller' you recommended earlier, an acquaintance (Adam Spiers, one of the inventors of the 'Enactive Torch') wrote me an email saying:

    "...your motors will need some kind of driver but
    depending on the size and type of the motor this could be
    as simple as a single TIP120 transistor as opposed to the
    controller you've been suggested (I'm not exactly sure
    what this is btw but it may be overkill)."


    What do you think? If I could use a "TIP120 transistor" to co-vary cmDistance and the current to a single eccentric motor, I could drop the whole servo idea and start the most important part: running the experiments. (Every day that goes by without this device completed is another day closer to law school rather than cognitive science & philosophy of mind :freaked: .) Thanks again Mike (and anyone else who would like to chime in).

    John
  • emblemofbeingemblemofbeing Posts: 9
    edited 2010-10-04 12:38
    This video I've made might give a better feel for what I'm working with, for anyone who is just beginning to read this thread:

    http://www.youtube.com/user/emblemOFbeing?feature=mhum#p/u/0/NfJ4oNkiHjg
  • emblemofbeingemblemofbeing Posts: 9
    edited 2010-10-04 14:30
    OK so, I've used a TIP120 transistor and a 1k-ohm resistor to hook the PS2 vibrating dc motor up to the PING))) sensor on my BS2. And I've had a glimpse of success! There is indeed some co-variation of motor speed (vibration) with the PING))) sensor distance. Unfortunately, there is a problem I need some assistance with, in terms of coding (see remarks below, following the code).

    ' 1) Measure distance with Ping))) sensor and display in cm,
    ' 2) Continuous and rapid conversion of measured distance to PWM -> vibrating dc motor.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}

    ' Conversion constant for room temperature PING))) measurements.
    CmConstant CON 2260

    distance VAR Word 'distance of reflected surface (3-300cm)
    time VAR Word
    vibe VAR Word 'duty cycle for PWM on pin 1, to dc motor (0-255) varying with distance variable

    PAUSE 3000 'initial 3 sec pause for programming purposes

    DO
    PULSOUT 15, 5
    PULSIN 15, 1, time

    distance = cmConstant ** time
    vibe = (distance*255)/297

    IF vibe > 255 THEN vibe = 255 'restricted vibe range: 3-255
    IF vibe < 3 THEN vibe = 3

    PWM 1, vibe, 100

    DEBUG HOME, DEC3 distance, " cm"
    DEBUG CR, DEC3 vibe, " PWM"

    LOOP


    My #1 problem: the 'distance' variable (3-300) modulates the 'vibe' variable (0-255)--which is what I've intended--but I need the relationship to be reversed! That is to say, right now: when distance is 300, vibe is 255. I need to reverse this, so that when distance is 300, vibe is much lower (3 is probably too low) and when distance is 3, vibe is 255, etc.

    There are other problems / imperfections, but this is the most obvious.
    I'm too tired to think of the solution right now, anyone see the (probably very simple) solution? vibe = 300-distance?
    Other recommendations are also welcome! (for instance, how might the PWM be improved, etc?)

    thanks,
    John
Sign In or Register to comment.