1

我在使用 IOIO 板控制步进电机时遇到了一些麻烦。我从 HelloIOIOPower 示例开始并添加了我的代码。当按下切换按钮时,程序将运行并打开/关闭 LED,但如果按下按钮改变 UI 线程中 motor_command 的值,则电机控制信号未设置,程序似乎挂起。它不会崩溃,但 LED 控制会丢失。

我尝试在 run 方法中的 switch 语句上使用 synchronized 以在允许更改 UI 线程中的 motor_control 之前评估整个 switch 语句。

我相信实现这一点的正确方法是绑定到 IOIO 线程,但我未能成功使其正常工作。

我希望能够更改“motor_control”的值,以创建对 IOIO 线程的控制命令以移动步进电机。一旦命令被执行,IOIO 线程将“motor_control”设置为零,这是一个注意或保持状态。

在服务中运行 IOIO 是首选但不是必需的。

我计划让这个应用程序 24/7 全天候运行,并向步进电机发送间歇性命令。当只有间歇性命令将发送到 IOIO 时,通过 IOIO 控制步进电机的正确方法是什么?

这是我在 Java/Android/IOIO 的第一次尝试,请随时指出所有错误,我很想了解我可以改进的地方......

谢谢...

` 包 com.medo.testmotor4;

import ioio.lib.api.DigitalOutput;
import ioio.lib.api.IOIO;
import ioio.lib.api.IOIOFactory;
import ioio.lib.api.exception.ConnectionLostException;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;


public class TestMotor4 extends Activity {
/** The text displayed at the top of the page. */
private TextView title_;
/** The toggle button used to control the LED. */
private ToggleButton button_;

Button full;
Button half;
Button step16th;
Button cup;
Button dish;
TextView cup_count;
TextView random_num;
int traycount = 0;  // try cup position
int motor_command = 0;    //motor command index value for switch statement




/** The thread that interacts with the IOIO. */
private IOIOThread ioio_thread_;

/**
 * Called when the activity is first created. Here we normally initialize
 * our GUI.
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test_motor4);
    title_ = (TextView) findViewById(R.id.title);
    button_ = (ToggleButton) findViewById(R.id.button);

// Assign value to Text Views:
    cup_count = (TextView)findViewById(R.id.tv_cup_count);
    cup_count.setText(Integer.toString(traycount));

    random_num = (TextView)findViewById(R.id.tv_random_number);
    random_num.setText("no number");


    // Set up buttons
    dish = (Button) findViewById(R.id.btn_dish);
    dish.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View arg0) {
            // call method that moves motor one full step
            motor_command = 4;      
            Toast.makeText(TestMotor4.this, "Motor_Command Set to: " + motor_command,Toast.LENGTH_SHORT).show();
        }
    });

    full = (Button) findViewById(R.id.btn_fullstep);
    full.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View arg0) {
            // call method that moves motor one full step
            motor_command = 1;  
            Toast.makeText(TestMotor4.this, "Motor_Command Set to: " + motor_command,Toast.LENGTH_SHORT).show();
        }
    });

    cup = (Button) findViewById(R.id.btn_cup);
    cup.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View arg0) {
            // call method that moves motor one full step
            traycount ++;
            if (traycount % 3 == 0 )    
                motor_command = 3;      // every 3rd tray cup move 54 1/8 steps 
                                        // all others move 53 1/8 steps
            else motor_command = 2; 
            Toast.makeText(TestMotor4.this, "Motor_Command Set to: " + motor_command,Toast.LENGTH_SHORT).show();
            cup_count.setText(Integer.toString(traycount));         
        }
    });

    half = (Button) findViewById(R.id.btnhalfstep);
    half.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View arg0) {
            // call method that moves motor one half step
            motor_command = 3;
                Toast.makeText(TestMotor4.this, "Motor_Command Set to: " + motor_command,Toast.LENGTH_SHORT).show();

        }
    });


}  //onCreate

/**
 * Called when the application is resumed (also when first started). Here is
 * where we'll create our IOIO thread.
 */
@Override
protected void onResume() {
    super.onResume();
    ioio_thread_ = new IOIOThread();
    ioio_thread_.start();
}

/**
 * Called when the application is paused. We want to disconnect with the
 * IOIO at this point, as the user is no longer interacting with our
 * application.
 */
@Override
protected void onPause() {
    super.onPause();
    ioio_thread_.abort();
    try {
        ioio_thread_.join();
    } catch (InterruptedException e) {
    }
}

/**
 * This is the thread that does the IOIO interaction.
 * 
 * It first creates a IOIO instance and wait for a connection to be
 * established. Then it starts doing the main work of opening the LED pin
 * and constantly updating it to match the toggle button's state.
 * 
 * Whenever a connection drops, it tries to reconnect, unless this is a
 * result of abort().
 */
class IOIOThread extends Thread {
    private IOIO ioio_;
    private boolean abort_ = false;

    DigitalOutput led;

    private DigitalOutput dir;
    private DigitalOutput stp;
    private DigitalOutput slp_,rst_, ms3, ms2, ms1,en_;
    private DigitalOutput led_;
    private DigitalOutput dish;
    private static final int STEP_WAIT = 5;


    /** Thread body. */
    @Override
    public void run() {
        super.run();
        while (true) {
            synchronized (this) {
                if (abort_) {
                    break;
                }
                ioio_ = IOIOFactory.create();
            }
            try {

                setText(R.string. wait_ioio);
                ioio_.waitForConnect();
                setText(R.string.ioio_connected);

                //IOIO pin setup:
                //DigitalOutput led = ioio_.openDigitalOutput(0, true);
                rst_ = ioio_.openDigitalOutput(13, true);   // /RESET   
                ms3  = ioio_.openDigitalOutput(14, true);   //  ms3  set step size     L L L full step
                ms2  = ioio_.openDigitalOutput(15, true);   //  ms2
                ms1  = ioio_.openDigitalOutput(16, true);   //  ms1                    H H H 1/16 step
                en_  = ioio_.openDigitalOutput(17, false);  // /enable 
                dir  = ioio_.openDigitalOutput(18, false);  //  DIRECTION -  set initial direction of motor rotation
                stp  = ioio_.openDigitalOutput(19, false);  //  STEP
                slp_ = ioio_.openDigitalOutput(20, true);       // /SLEEP  - 
                led  = ioio_.openDigitalOutput(IOIO.LED_PIN);
                dish = ioio_.openDigitalOutput(9, false);   // Dish - linear actuator activate signal   
                Log.d ("IOIOLooper setup", "Complete");
                int test = 0;


                Toast.makeText(TestMotor4.this, "Starting while loop",Toast.LENGTH_SHORT).show();
                while (true) {

                    led.write(!button_.isChecked());


                    switch(motor_command){

                        case 0:  // hold - do nothing for 5 sec.
                            this.timeout(100);

                            break;

                        case 1:   //full step on motor
                            full();
                            Log.d("STEPPER-FULL","Complete");
                            motor_command = 0;                  
                            break;

                        case 2:  // move motor 1 cup - (53) 1/8 steps
                            cup(53);
                            motor_command = 0; 
                            Log.d("STEPPER-CUP - 53","Complete" );
                            break;

                        case 3: // move motor 1 cup (54) 1/8 steps
                            cup(54);
                            motor_command = 0; 
                            Log.d("STEPPER-CUP - 54","Complete" );
                            break;

                        case 4: // dump scoop dish
                            dish.write(true);
                            //Toast.makeText(TestMotor4.this, "Dish set HIGH: ",Toast.LENGTH_SHORT).show();
                            this.timeout(5000);
                            dish.write(false);
                            //Toast.makeText(TestMotor4.this, "Dish set LOW " + motor_command,Toast.LENGTH_SHORT).show();
                            motor_command = 0;
                            break;

                    } // switch
                    sleep(10);

                }
            } catch (ConnectionLostException e) {
                setText(R.string.connectionLost);

            } catch (Exception e) {
                Log.e("TestMotor4", "Unexpected exception caught", e);
                ioio_.disconnect();
                break;
            } finally {
                    if (ioio_ != null) {
                        try {
                            ioio_.waitForDisconnect();
                        } catch (InterruptedException e) {
                        }
                    }
                    synchronized (this) {
                        ioio_ = null;
                    }
            }
        } // while(true)
    }// Run 


    /**
     * Abort the connection.
     * 
     * This is a little tricky synchronization-wise: we need to be handle
     * the case of abortion happening before the IOIO instance is created or
     * during its creation.
     */
    synchronized public void abort() {
        abort_ = true;
        if (ioio_ != null) {
            ioio_.disconnect();
        }
    }// abort

    /**
     * Set the text line on top of the screen.
     * 
     * @param id
     *            The string ID of the message to present.
     */
    private void setText(final int id) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                title_.setText(getString(id));
            }
        });
    } //setText

    public void full ()throws ConnectionLostException{
        // move motor 1 full step  (1.8 degrees)
        // requires stp to be LOW before entering method  - leaves stp LOW on exit of method
        try{
            en_.write(false);  // enable MC outputs
        // configure for full step  ( L L L)
            ms1.write(false);
            ms2.write(false);               
            ms3.write(false);
            Log.d("Set FULL", "L L L");

        //send step signal with LOW To HIGH transition
            stp.write(true);
            timeout(STEP_WAIT);
            stp.write(false);
            this.timeout(STEP_WAIT); 
        }catch(ConnectionLostException e) {
            //enableUi(false);
            Toast.makeText(TestMotor4.this, "IOIO Connection Lost ",Toast.LENGTH_LONG).show();
            throw e;
        }
    } // full

    public void cup(int num) throws ConnectionLostException{
        try{                    
            // set step size to 1/8 step
            ms1.write(true);
            ms2.write(true);
            ms3.write(false);
            Log.d("Set 1/8 step size ", "H H L");
            // set up wait for signals to stabilize
            this.timeout(STEP_WAIT); 


            //move motor 53 steps
            for (int i = 0; i<num; i++){
                stp.write(true);
                this.timeout(STEP_WAIT); 
                stp.write(false);
                this.timeout(STEP_WAIT); 
            }

        }catch (ConnectionLostException e){
            Toast.makeText(TestMotor4.this, "IOIO Connection Lost ",Toast.LENGTH_LONG).show();
            throw e;
        }
    }   //cup   
    private void timeout(int ms) {
        try {
        sleep(ms);
        } catch (InterruptedException e) {
        // Do nothing...
        }
        }

}  //IOIOThread

}`

4

0 回答 0