Android Things v1中OnTouch无法停止GPIO控制电机的问题
解决Android Things中按钮松开后电机无法停止的问题
嘿,我来帮你排查这个问题!你现在遇到的情况是按下按钮电机启动,但松开后停不下来,咱们先看看你修改后的代码里的几个关键问题:
现有代码的核心问题
- 重复打开GPIO端口:每次按下按钮(
ACTION_DOWN)都重新调用manager.openGpio("BCM24"),这会导致之前的GPIO实例没有被正确释放,后续的操作可能因为资源冲突失效。 - 错误的停止方式:你在
ACTION_UP时直接调用mtrGpio.close(),这是关闭了GPIO端口,而不是让电机停止。正确的做法应该是把GPIO的输出值设为false,而不是关闭端口。
修正后的解决方案
我们需要调整GPIO的初始化时机,只在Activity启动时初始化一次,然后在触摸事件里仅控制GPIO的输出状态,最后在Activity销毁时释放GPIO资源。
完整修正代码
public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private static final String MOTOR_GPIO_PIN = "BCM24"; private Gpio mtrGpio; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button mtrbtnGD = (Button) findViewById(R.id.mtrbtn); Button closebtn = (Button) findViewById(R.id.closebtn); Button stopmtrbtn = (Button) findViewById(R.id.stopmtrbtn); // 初始化GPIO initMotorGpio(); // 按钮触摸事件处理 mtrbtnGD.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mtrGpio == null) { Log.w(TAG, "Motor GPIO not initialized"); return false; } try { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 按下按钮,启动电机 mtrGpio.setValue(true); Log.i(TAG, "Motor started"); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 松开按钮或触摸被中断,停止电机 mtrGpio.setValue(false); Log.i(TAG, "Motor stopped"); return true; } } catch (IOException e) { Log.w(TAG, "Unable to control motor GPIO", e); } return false; } }); } /** * 初始化电机GPIO端口 */ private void initMotorGpio() { PeripheralManager manager = PeripheralManager.getInstance(); List<String> portList = manager.getGpioList(); if (portList.isEmpty()) { Log.i(TAG, "No GPIO port available on this device."); return; } else { Log.i(TAG, "List of available ports: " + portList); } try { mtrGpio = manager.openGpio(MOTOR_GPIO_PIN); mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE); mtrGpio.setActiveType(Gpio.ACTIVE_HIGH); mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); Log.i(TAG, "Motor GPIO initialized successfully"); } catch (IOException e) { Log.w(TAG, "Unable to initialize motor GPIO", e); mtrGpio = null; } } @Override protected void onDestroy() { super.onDestroy(); // 销毁时释放GPIO资源 if (mtrGpio != null) { try { mtrGpio.close(); Log.i(TAG, "Motor GPIO closed"); } catch (IOException e) { Log.w(TAG, "Unable to close motor GPIO", e); } } } }
关键修改点说明
- 提前初始化GPIO:在
onCreate里调用initMotorGpio()一次性初始化GPIO端口,避免重复打开导致的资源问题。 - 正确控制电机状态:
ACTION_DOWN时设置setValue(true)启动电机,ACTION_UP和ACTION_CANCEL时设置setValue(false)停止电机(加上ACTION_CANCEL是为了处理触摸意外中断的情况,比如滑动离开按钮)。 - 资源释放:在
onDestroy方法里关闭GPIO端口,确保Activity销毁时释放硬件资源。
这样修改后,你按下按钮电机启动,松开按钮电机就会停止了。
内容的提问来源于stack exchange,提问作者Faz
相关产品推荐
相关产品推荐

