Shop OBEX P1 Docs P2 Docs Learn Events
Need help with Memsic 2125 — Parallax Forums

Need help with Memsic 2125

arnoarno Posts: 43
edited 2006-03-28 14:42 in General Discussion
Helo all,
I try to do a sensor detecto with a Javelin and a memsic 2125, but it's look like it's not working, and I need some help with it.
so here is my code :
import stamp.core.*;
import stamp.util.*;
import stamp.peripheral.*;
import java.lang.*;


public class tracker1 {
final static int xIn = CPU.pin5; // Memsic 2125 input pin X
final static int yIn = CPU.pin6; // Memsic 2125 input pin Y

final static int SampleDelay = 500;
final static int AlarmLevel = 5;
final static int xLimit = 5;
final static int yLimit = 5;

static boolean CarMove = false;
static int xCal;
static int yCal;
static int xMove;
static int yMove;
static int xDiff;
static int yDiff;
static int moTimer;


static void Initialize() {
StringBuffer buf=new StringBuffer(79);
//calibration value for the motion detector
moTimer = 0;
xCal = CPU.pulseIn( 1200, xIn, true);
yCal = CPU.pulseIn( 1200, yIn, true);
xCal = xCal / 10; // some cleanup, for noise and temp
yCal = yCal / 10; // some cleanup, for noise and temp
buf.append( "xCal: " );
buf.append( xCal );
buf.append( ", yCal: " );
buf.append( yCal );
buf.append( "\n\r" );

System.out.println(buf.toString());


}

//
[noparse][[/noparse] Motion Detection ]
static void Motion(){
StringBuffer buf=new StringBuffer(79);
System.out.print("motion loop");
do {
xMove = CPU.pulseIn( 1200, xIn, true);
yMove = CPU.pulseIn( 1200, yIn, true);
xMove = xMove / 10; // some cleanup, for noise and temp
yMove = yMove / 10; // some cleanup, for noise and temp

xDiff = Math.abs ( xMove - xCal);
yDiff = Math.abs ( yMove - yCal);
if ( (xDiff > xLimit) || (yDiff > yLimit) ) {
moTimer = moTimer + 1;
}
if ( moTimer > AlarmLevel ) {
CarMove = true;
}
else {
moTimer = 0;
buf.append( "moTimer: " );
buf.append( moTimer );
buf.append( ", xMove: " );
buf.append( xMove );
buf.append( ", yMove: " );
buf.append( yMove );
buf.append( "\n\r" );

System.out.println(buf.toString());
}
} while (!CarMove);
buf.append( "it has moved !!" );
buf.append( ", xMove: " );
buf.append( xMove );
buf.append( ", yMove: " );
buf.append( yMove );
buf.append( "\n\r" );

System.out.println(buf.toString());
}

public static void main(){
Initialize();
// Wait until the car has moved !
Motion();

}
}


any advice/help will be very valuable,
thanks

arno

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-27 15:02
    There is a memsic2125 class here (including testprogram)
    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/peripheral/sensor/accelerometer/
    Check that out to see how it is done.
    regards peter

    ·
  • arnoarno Posts: 43
    edited 2006-03-28 06:34
    Hmm interesting, but I did read all the sample.
    And I take my code from a Nuts&volts article that was write for the basic stamp, regarding a motion detector.
    So that's why I have some problem with my code, I was expecting someone to read my code, not put me a link to some sample.

    thanks anyway !
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-28 07:00
    You need to be more precise about what is not working.
    Where in your code do you get unexpected or no results?
    That would help to pinpoint any errors.

    The other class is supposed to work (I really can't tell if it is
    as I don't use a memsic2125) and so how it interfaces to
    the memsic2125 is a way to find out if your interface differs
    which may be the cause for your class not working.

    regards peter
  • arnoarno Posts: 43
    edited 2006-03-28 08:05
    For the this part:
    xCal = CPU.pulseIn( 1200, xIn, true);
    yCal = CPU.pulseIn( 1200, yIn, true);
    xCal = xCal / 10; // some cleanup, for noise and temp
    yCal = yCal / 10; // some cleanup, for noise and temp
    buf.append( "xCal: " );
    buf.append( xCal );
    buf.append( ", yCal: " );
    buf.append( yCal );
    buf.append( "\n\r" );

    System.out.println(buf.toString());

    I get 56 for xCal and 57 for Ycal, and dosen't matter if I change the position of the board.

    for this part:
    xMove = CPU.pulseIn( 1200, xIn, true);
    yMove = CPU.pulseIn( 1200, yIn, true);
    xMove = xMove / 10; // some cleanup, for noise and temp
    yMove = yMove / 10; // some cleanup, for noise and temp

    xDiff = Math.abs ( xMove - xCal);
    yDiff = Math.abs ( yMove - yCal);
    if ( (xDiff > xLimit) || (yDiff > yLimit) ) {
    moTimer = moTimer + 1;
    }
    if ( moTimer > AlarmLevel ) {
    CarMove = true;
    }
    else {
    moTimer = 0;
    buf.append( "moTimer: " );
    buf.append( moTimer );
    buf.append( ", xMove: " );
    buf.append( xMove );
    buf.append( ", yMove: " );
    buf.append( yMove );
    buf.append( "\n\r" );

    System.out.println(buf.toString());

    I get 0 for both value and I can shack my board as I wan't nothing change !?!?
    And that's make me thing something is wrong.
    I did the connection like it suppose to be,as explain on the doc of the memsic
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-28 10:33
    In the other class, the value 10000 is used in pulseIn.
    I also saw another class where 2000 was used.
    It might be your 1200 is too low.
    Please try your code with these new timeout values.

    regards peter
    ·
  • arnoarno Posts: 43
    edited 2006-03-28 10:59
    I did a test with 10000, and still same output:
    xCal: 57, yCal: 57

    moTimer: 0, xMove: 57, yMove: 57, xDiff: 0, yDiff: 0
    moTimer: 0, xMove: 57, yMove: 57, xDiff: 0, yDiff: 0

    moTimer: 0, xMove: 57, yMove: 57, xDiff: 0, yDiff: 0
    moTimer: 0, xMove: 57, yMove: 57, xDiff: 0, yDiff: 0
    moTimer: 0, xMove: 57, yMove: 57, xDiff: 0, yDiff: 0

    moTimer: 0, xMove: 57, yMove: 57, xDiff: 0, yDiff: 0


    and here is the code I did on basic Stamp Working and the value is close to 663 for X and Y
    HiPulse CON 1
    LoPulse CON 0
    SampleDelay CON 500
    AlarmLevel CON 5
    xLimit CON 2
    yLimit CON 2
    '
    [noparse][[/noparse] Motion detection Variables ]
    xCal VAR Word
    yCal VAR Word
    xMove VAR Word
    yMove VAR Word
    xDiff VAR Word
    yDiff VAR Word
    moTimer VAR Word

    CarMove VAR Byte

    '
    [noparse][[/noparse] Main Code ]
    Main:
    DEBUG "main start"
    DEBUG CR

    GOSUB Initialize

    MainLoop:
    GOSUB Motion ' wait for car to move
    GOSUB SmsMessage ' send SMS advice car is moving
    IF ( CarMove = 0 ) THEN
    GOTO MainLoop
    ENDIF
    END


    Initialize:
    PULSIN 5, HiPulse, xCal
    PULSIN 6, HiPulse, yCal
    xCal = xCal / 10 ' some cleanup, for noise and temp
    yCal = yCal / 10 ' some cleanup, for noise and temp


    Motion:
    DEBUG "motion loop"
    DO
    PULSIN 5, HiPulse, xMove
    PULSIN 6, HiPulse, yMove
    xMove = xMove / 10 ' some cleanup, for noise and temp
    yMove = yMove / 10 ' some cleanup, for noise and temp
    PAUSE SampleDelay

    xDiff = ABS ( xMove - xCal)
    yDiff = ABS ( yMove - yCal)
    IF (xDiff > xLimit) OR (yDiff > yLimit) THEN
    moTimer = moTimer + 1
    ELSE
    moTimer = 0
    ENDIF
    IF ( moTimer > AlarmLevel ) THEN Carmove = 1
    LOOP UNTIL (Carmove = 1)

    RETURN


    I think you are right on it about theis timeout value, it's the only point I'm not sure what it mean. In memsic the pulse suppose to bo something like 10milisec, and for what I understand the timeout is multiple of 8 usec (so arround 1250 sould be fine)
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-28 11:50
    Javelin pulsIn

    pulseIn

    public static int pulseIn(int·timeout, int·portPin, boolean·pinState)Measure the length of a single pulse. Waits for the value of the selected pin to match the value selected by the state parameter and then times how long it takes for the pin to return to its original state. If the pin is an output then it will be changed to be an input and will remain as an input when complete.

    A pulse of less than 8.68us in duration may be missed.

    Parameters: timeout - the maximum amount of time to spend in the pulseIn method. The timeout covers the complete time of the process—both the wait for the start of the pulse and the time of the pulse. portPin - the I/O pin to measure the pulse on. pinState - whether to measure a high pulse (true) or a low pulse (false). Returns: the length of the pulse in 8.68us units. A value of 0 indicates that no start edge was detected. A value of -1 indicates that no stop edge was detected.
    Basic Stamp pulsIn

    Function
    Measure the width of a pulse on Pin described by State and store the result in Variable.
    • Pin is a variable/constant/expression* (0 - 15) that specifies the I/O pin to use. This pin will be set to input mode.
    • State is a variable/constant/expression* (0 - 1) that specifies whether the pulse to be measured is low (0) or high (1). A low pulse begins with a 1-to-0 transition and a high pulse begins with a 0-to-1 transition.
    • Variable is a variable (usually a word) in which the measured pulse duration will be stored. The unit of time for Variable is described below.

    attachment.php?attachmentid=73642

    Quick Facts
    attachment.php?attachmentid=73643

    Explanation
    PULSIN is like a fast stopwatch that is triggered by a change in state (0 or 1) on the specified pin. The entire width of the specified pulse (high or low) is measured, in units shown above and stored in Variable.

    Many analog properties (voltage, resistance, capacitance, frequency, duty cycle) can be measured in terms of pulse duration. This makes PULSIN a valuable form of analog-to-digital conversion.

    PULSIN will wait for the desired pulse, for up to the maximum pulse width it can measure, shown in the table above. If it sees the desired pulse it measures the time until the end of the pulse and stores the result in Variable. If it never sees the start of the pulse, or the pulse is too long (greater than the Maximum Pulse Width shown above), PULSIN "times out" and store 0 in Variable. This operation keeps your program from locking-up should the desired pulse never occur.

    Regardless of the size of Variable, PULSIN internally uses a 16-bit timer. Unless the pulse widths are known to be short enough to fit in an 8-bit result, it is recommended using a word-sized variable. Not doing so may result in strange and misleading results as the BASIC Stamp will only store the lower 8-bits into a byte variable.



    If you measure 660 on a BS2 then you should get 660/(8.68/2) = 660/4.34 = 152 on a javelin

    This factor 4.34 also relates to your difference calculation. On a bs2sx the factor is 8.68/0.8 = 10.85
    (10.85*57 = 618 !! Did you use a bs2sx???)
    I think because·the javelin count values are smaller then the BS2 count values
    you must adjust your level values. (or do not divide by 10, but by 10/4.34 = 2)
    and keep your level values.



    Try that.
    regards peter
    721 x 36 - 3K
    549 x 133 - 6K
  • arnoarno Posts: 43
    edited 2006-03-28 12:16
    Whell, thanks for all this info, in the mean time I try to find some other post, and there is an error in the Accelerometer.java (see the following post at the end)

    http://forums.parallax.com/forums/default.aspx?f=8&m=87192

    As I try to change my code (using the acce
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-28 12:28
    Do you use a bs2sx/bs2p/bs2px ??
    That would explain the value 57 you got.
    regards peter
  • arnoarno Posts: 43
    edited 2006-03-28 12:41
    it's a BS2p

    One more question: how did you handle an 'outOfMemoryError ?

    After a while my program just crash (a while is a something like 30-45 second)

    I know there is some issue about constructo/destructor not handle as it should be (system.out is one of them) but how can I find which function I have to care about this kind of problem ?

    thanks in advance
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-28 12:49
    For this accelerometer class

    ··· // Longest onTime interval is 32,767/50 = 655 * 8.62uS
    ··· return ( (50 * onTime) / (t2Time / 2) );

    The problem there is overflow due to 50*onTime
    The formula really equals 100*(onTime/t2Time) where t2Time>onTime

    My class UnsignedIntMath has a method ufrac that calculates a fraction for 65536 base

    int fr = UnsignedIntMath.ufrac(onTime/t2Time);

    It also has a method of multiplying an integer with a 65536 based fraction

    return UnsignedIntMath.umulf(100,fr); //return dutycyle in percentage (0-99)
    or
    return UnsignedIntMath.umulf(10000,fr); //return dutycyle in 0.01 percentage (0-9999)

    So the Int32 class can be replaced by the UnsignedIntMath class (which is much smaller)

    You can put it all in a single line

    return UnsignedIntMath.umulf(100,UnsignedIntMath.ufrac(onTime,y2Time)); //dutycyle in percentage (0-99)

    You find the UnsignedIntMath class here

    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/math/

    regards peter



    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-03-28 12:57
    I think the outofmemory is due to buf.toString() used in System.out
    toString creates a temporary string and for System.out not required I believe
    because System.out.print(buf) also works.
    I usually use the Format class which does not use the String at all
    and it allows to print values using several bases (bin,octal,dec,hex)
    The Format class can be found here:
    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/util/text/

    Another good practice is not to use the keyword 'new' inside methods.
    Create global buffers only.

    regards peter
  • arnoarno Posts: 43
    edited 2006-03-28 14:42
    Yup taht was the problem the new for the math stuff inside my code.
    So I did globaly and now it's ok

    Thanks for your help Peter
Sign In or Register to comment.