Data abort after a few time

This is where you talk about the NXJ software itself, installation issues, and programming talk.

Moderators: 99jonathan, roger, imaqine

Data abort after a few time

Postby vladra » Sat Nov 17, 2007 4:22 am

Lego Nxt.

This is a program for test/calibrate sensors (like a program in "View" menu of Lego firmware).
But it is run about a minute and then "Data abort" message is displayed:

Data abort
PC 00104AF2
AASR 18F09FE6
ASR 00020001

What's happened? I don't undestand. Is it a problem of my program or of leJOS?
Could you help me?


Code: Select all
import lejos.nxt.*;

public class SensorsMain implements SensorPortListener
{
    private static final String CURRENT_MESSAGE = "cur";
    private static final String MAX_MESSAGE = "max";
    private static final String MIN_MESSAGE = "min";
    private static final String AVG_MESSAGE = "avg";

    private static final String CLEAR = "            ";

    private final SensorType[] _sensors = {
            new TouchSensorType(),
            new LightSensorType(true),
            new LightSensorType(false),
            new SoundSensorType(true),
            new SoundSensorType(false),
            new UltrasonicSensorType()
    };

    private final SimpleMenu _sensorMenu;
    private final SimpleMenu _portMenu = new SimpleMenu("Select port", new String[] {"1", "2", "3", "4"});

    private SensorType _currentSensor = null;
    private boolean _started = false;

    private int _val;
    private int _maxval;
    private int _minval;
    private int _avgval;
    private int _sumval;
    private int _count;

    public SensorsMain()
    {
        String[] sensorTitles = new String[_sensors.length];
        for( int index = 0; index<_sensors.length; index++ )
        {
            sensorTitles[index] = _sensors[index].getTitle();
        }
        _sensorMenu = new SimpleMenu("Select sensor", sensorTitles);

        for( int index = 0; index<SensorPort.PORTS.length; index++ )
        {
            SensorPort.PORTS[index].addSensorPortListener(this);
        }
    }

    public static void main(String[] args)
    {
        try
        {
            new SensorsMain().run();
        } catch (Throwable e)
        {   // it isn't work to display error message!

            try { Thread.sleep(500); }
            catch (InterruptedException ignored) {}

            LCD.clear();
            LCD.drawString(e.getMessage(), 0, 0);
            LCD.refresh();

            try { Thread.sleep(5000); }
            catch (InterruptedException ignored) {}
        }
    }

    public void run() throws Throwable
    {
        while( _sensorMenu.run() )  // select sensor type
        {
            _currentSensor = _sensors[_sensorMenu.getSelection()];
            _portMenu.setSelection(_currentSensor.getDefaultPortIndex());

            if( _portMenu.run() )   // select sensor port
            {
                initScreen();
                _currentSensor.start(SensorPort.PORTS[_portMenu.getSelection()]);
                resetValues();
                Thread.sleep(500);

                while( Button.readButtons()==0 )
                {
                    displayValues();
                    Thread.sleep(50);
                }

                _started = false;
                _currentSensor.stop();
            }
        }
    }

    private void resetValues()
    {
        _val = 0;
        _maxval = -2000;
        _minval = 2000;
        _avgval = 0;
        _sumval = 0;
        _count = 0;
        _started = true;
    }

    private void initScreen()
    {
        LCD.clear();
        LCD.drawString(_currentSensor.getTitle(), 0, 0);
        LCD.drawString(CURRENT_MESSAGE, 0, 1);
        LCD.drawString(MAX_MESSAGE, 0, 2);
        LCD.drawString(MIN_MESSAGE, 0, 3);
        LCD.drawString(AVG_MESSAGE, 0, 4);
        LCD.refresh();
    }

    private void displayValues()
    {
        LCD.drawString(CLEAR, 4, 1);
        LCD.drawInt(_val, 4, 1);

        LCD.drawString(CLEAR, 4, 2);
        LCD.drawInt(_maxval, 4, 2);

        LCD.drawString(CLEAR, 4, 3);
        LCD.drawInt(_minval, 4, 3);

        LCD.drawString(CLEAR, 4, 4);
        LCD.drawInt(_avgval, 4, 4);

        LCD.refresh();
    }

    public void stateChanged(SensorPort aSource, int aOldValue, int aNewValue)
    {
        if( !_started || _currentSensor.getPort()!=aSource )
            return;

        // i think it isn't necessary synchronization for display these variables
        _val = _currentSensor.getValue();
        if( _maxval<_val )
            _maxval = _val;
        if( _minval>_val )
            _minval = _val;

        if( _count>10000 )
        {
            _count = 0;
            _sumval = 0;
            _avgval = 0;
        }
        _count++;
        _sumval += _val;
        _avgval = _sumval/_count;
    }
}


Code: Select all
import lejos.nxt.LCD;
import lejos.nxt.Button;

public class SimpleMenu
{
    private static final String SELECT_MARKER = ">";
    private static final String SPACE_MARKER = " ";

    private final String _header;
    private final String[] _alternatives;

    private int _selection;
    private int _topindex = 0;

    public SimpleMenu(String header, String[] alternatives)
    {
        this(header, alternatives, 0);
    }

    public SimpleMenu(String header, String[] alternatives, int selection)
    {
        _header = header;
        _alternatives = alternatives;
        setSelection(selection);
    }

    public String getHeader()
    {
        return _header;
    }

    public String[] getAlternatives()
    {
        return _alternatives;
    }

    public int getSelection()
    {
        return _selection;
    }

    public void setSelection(int selection)
    {
        if( selection<0 )
            selection = _alternatives.length-1;
        else if( selection>=_alternatives.length )
            selection = 0;

        _selection = selection;
        if( selection<_topindex )
            _topindex = selection;
        else if( selection > _topindex+LCD.DISPLAY_CHAR_DEPTH-2 )
            _topindex = _selection-LCD.DISPLAY_CHAR_DEPTH+2;
    }

    /**
     * selection process
     * @return true if user press Enter, false if user press Escape
     */
    public boolean run()
    {
        drawScreen();

        try { Thread.sleep(500); }
        catch (InterruptedException ignored) {}

        int buttonCode;
        while(true)
        {
            buttonCode = Button.waitForPress();
            if( buttonCode==Button.ESCAPE.getId() )
                return false;

            if( buttonCode==Button.ENTER.getId() )
                return true;

            changeSelection(_selection + (buttonCode==Button.LEFT.getId() ? -1 : 1));
        }
    }

    /**
     * set new selection and refresh LCD
     * @param newselection
     */
    private void changeSelection(int newselection)
    {
        int oldtop = _topindex;
        int oldselection = _selection;
        setSelection(newselection);
        if( oldselection!=_selection )
        {
            if( oldtop==_topindex )
            {
                drawItem(oldselection, getIndexLine(oldselection));
                drawItem(_selection, getIndexLine(_selection));
                LCD.refresh();
            }
            else
                drawScreen();
        }
    }

    /**
     * draw screen entirely
     */
    private void drawScreen()
    {
        LCD.clear();

        int x = (LCD.DISPLAY_CHAR_WIDTH - _header.length())/2;
        if( x<0 )
            x = 0;

        LCD.drawString(_header, x, 0);

        for( int line = 1, index=_topindex; line<LCD.DISPLAY_CHAR_DEPTH && index<_alternatives.length; line++, index++ )
        {
            drawItem(index, line);
        }

        LCD.refresh();
    }

    /**
     * draw specified item only
     * LCD.refresh is required
     */
    private void drawItem(int index, int line)
    {
        LCD.drawString(index==_selection ? SELECT_MARKER : SPACE_MARKER, 0, line);
        LCD.drawString(_alternatives[index], 1, line);
    }

    /**
     * display line of the index
     * @param index
     * @return [1, LCD.DISPLAY_CHAR_DEPTH)
     */
    private int getIndexLine(int index)
    {
        return index-_topindex+1;
    }
}


Code: Select all
import lejos.nxt.SensorPort;
import lejos.nxt.SensorConstants;

public abstract class SensorType implements SensorConstants
{
    private final int _defaultPortIndex;
    private final String _title;
    private SensorPort _port;

    protected SensorType(String title, int defaultPortIndex)
    {
        _title = title;
        _defaultPortIndex = defaultPortIndex;
    }

    public void start(SensorPort port)
    {
        _port = port;
        init();
    }

    public void stop()
    {
        release();
        _port = null;
    }

    public int getDefaultPortIndex()
    {
        return _defaultPortIndex;
    }

    public String getTitle()
    {
        return _title;
    }

    public abstract int getValue();
   
    protected abstract void init();

    public SensorPort getPort()
    {
        return _port;
    }

    protected void release()
    {
        _port.setType(TYPE_NO_SENSOR);
    }
}


Code: Select all
public class LightSensorType extends SensorType
{
    private final boolean _active;

    public LightSensorType(boolean active)
    {
        super(active ? "Active light" : "Passive light", 2);
        _active = active;
    }

    public int getValue()
    {
        return ((1023 - getPort().readRawValue()) * 100/ 1023);
    }

    protected void init()
    {
        getPort().setTypeAndMode(_active ? TYPE_LIGHT_ACTIVE : TYPE_LIGHT_INACTIVE,
                            MODE_PCTFULLSCALE);
    }
}


Code: Select all
public class SoundSensorType extends SensorType
{
    private final boolean _dba;

    public SoundSensorType(boolean dba)
    {
        super(dba ? "Sound DBa" : "Sound DB", 1);
        _dba = dba;
    }

    public int getValue()
    {
        return ((1023 - getPort().readRawValue()) * 100/ 1023);
    }

    protected void init()
    {
        getPort().setTypeAndMode(
                (_dba ? TYPE_SOUND_DBA
                     : TYPE_SOUND_DB),
                MODE_PCTFULLSCALE);
    }
}


Code: Select all
public class TouchSensorType extends SensorType
{
    public TouchSensorType()
    {
        super("Touch", 0);
    }


    public int getValue()
    {
        return getPort().readRawValue()<600 ? 1 : 0;
    }

    protected void init()
    {
        getPort().setTypeAndMode(TYPE_SWITCH, MODE_BOOLEAN);
    }
}


Code: Select all
public class UltrasonicSensorType extends SensorType
{
    private final byte[] buf = new byte[1];
    private int address = 1;

    public UltrasonicSensorType()
    {
        super("Ultrasonic", 3);
    }

    public int getValue()
    {
        int ret = getData(0x42, buf, 1);
        return (ret == 0 ? (buf[0] & 0xff) : 255);
    }

    protected void init()
    {
        SensorPort port = getPort();
        port.i2cEnable();
      port.setType(TYPE_LOWSPEED);
    }

    protected void release()
    {
        super.release();
        getPort().i2cDisable();
    }

    private int getData(int register, byte [] buf, int len) {
        int ret = getPort().i2cStart(address, register, len, buf, len, 0);

        if (ret != 0) return ret;

        while (getPort().i2cBusy() != 0) {
            Thread.yield();
        }

        return 0;
    }
}
vladra
New User
 
Posts: 24
Joined: Fri Nov 16, 2007 6:18 pm
Location: Russia

Postby lawrie » Sat Nov 17, 2007 3:11 pm

It is probably a leJOS problem if it happens consistently. Data aborts occur when an incomplete program is run, e.g. when the flash memory fills. Other data aborts are likely to be leJOS problems.

I will look at this when I get some time.
lawrie
leJOS Team Member
 
Posts: 934
Joined: Mon Feb 05, 2007 1:27 pm

Postby vladra » Sun Nov 18, 2007 3:20 am

When I improve this program the problem eliminated.
The following code is replaced with LCD.drawInt(_val, 4, 4, 1);
Code: Select all
LCD.drawString(CLEAR, 4, 1);
LCD.drawInt(_val, 4, 1);


Ultrasonic sensor shouldn't use SensorPortListener. Instead of listener _currentSensor.getValue() is used in display values loop. It works properly.

I like leJOS.
vladra
New User
 
Posts: 24
Joined: Fri Nov 16, 2007 6:18 pm
Location: Russia


Return to NXJ Software

Who is online

Users browsing this forum: No registered users and 4 guests

more stuff