IOIO ボードを使用したステッピング モーターの制御に問題があります。HelloIOIOPower の例から始めて、コードを追加しました。トグル ボタンが押されると、プログラムが実行され、LED のオン/オフが切り替えられますが、ボタンが押されて UI スレッドの motor_command の値が変更されると、モーター制御信号が設定されず、プログラムがハングしたように見えます。クラッシュはしませんが、LED 制御が失われます。
run メソッドの switch ステートメントで synchronized を使用して、UI スレッドで motor_control を変更できるようにする前に、switch ステートメント全体を評価してみました。
これを実装する正しい方法は IOIO スレッドにバインドすることだと思いますが、それを正しく機能させることができませんでした。
「motor_control」の値を変更して、ステッピング モーターを動かす IOIO スレッドへの制御コマンドを作成できるようにしたいと考えています。コマンドが実行されると、IOIO スレッドは「motor_control」をゼロに設定します。これは、無視または保留状態です。
サービスで IOIO を実行することをお勧めしますが、必須ではありません。
断続的なコマンドをステッピング モーターに送信して、このアプリを 24 時間年中無休で実行する予定です。断続的なコマンドのみが 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
}`