You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:34:50