diff --git a/app/src/main/java/com/ismart/ib86/app/MainActivity.java b/app/src/main/java/com/ismart/ib86/app/MainActivity.java index 39a45bf..33881c8 100644 --- a/app/src/main/java/com/ismart/ib86/app/MainActivity.java +++ b/app/src/main/java/com/ismart/ib86/app/MainActivity.java @@ -1,9 +1,7 @@ package com.ismart.ib86.app; import android.Manifest; -import android.annotation.SuppressLint; import android.content.pm.PackageManager; -import android.graphics.Color; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; @@ -13,7 +11,7 @@ import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.os.Message; +import android.view.KeyEvent; import android.view.Window; import android.view.WindowInsets; import android.view.WindowInsetsController; @@ -22,7 +20,6 @@ import android.view.View; import android.util.Log; import android.widget.Button; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; @@ -32,14 +29,10 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.ismart.ib86.feature.serial.SerialPort.ASR5515Protocol; -import com.ismart.ib86.feature.serial.SerialPort.SerialPortHelper; import com.ismart.ib86.feature.gpio.GpioManager; import com.ismart.ib86.feature.serial.SerialPort.ASR5515DeviceManager; -import com.ismart.ib86.feature.serial.SerialPort.ASR5515Protocol; import com.ismart.ib86.common.utils.LogManager; -import com.ismart.ib86.feature.gpio.GpioTest; import com.ismart.ib86.feature.motor.MotorController; -import com.ismart.ib86.view.RobotEyesView; import com.lhht.xiaozhi.models.websokcet.send.WebSocketSendMsgFactory; import com.lhht.xiaozhi.settings.SettingsManager; import com.lhht.xiaozhi.utils.DeviceUtils; @@ -52,9 +45,11 @@ import java.util.concurrent.Executors; import vip.inode.demo.opusaudiodemo.utils.OpusUtils; -public class MainActivity extends AppCompatActivity implements WebSocketManager.WebSocketListener{ +public class MainActivity extends AppCompatActivity implements WebSocketManager.WebSocketListener { private static final String TAG = "MainActivity"; private static final String DEVICE_PATH = "/dev/ttyS3"; + + private static final int HEAD_TOUCH_KEY = 285; private static final int BAUD_RATE = 921600; // 权限请求码 @@ -95,6 +90,7 @@ public class MainActivity extends AppCompatActivity implements WebSocketManager. private short[] decodedBuffer; private short[] recordBuffer; private byte[] encodedBuffer; + private boolean hasStartedCall = false; private boolean isRecording = false; private volatile boolean isDestroyed = false; @@ -102,17 +98,25 @@ public class MainActivity extends AppCompatActivity implements WebSocketManager. private boolean isPlaying = false; private String sessionId = ""; // 添加session_id字段 private long lastAudioDataTime = 0; // 新增:记录最后一次收到音频数据的时间 + private Thread motorControlThread; // 用于跟踪电机控制线程 private boolean isCheckingPlaybackStatus = false; - - - //xiaozhi end - + // HeadTouchManager removed // UI控件 private ImageView ivFace; + private Button btnRotateForward; + private Button btnRotateReverse; + private SeekBar seekBarDutyCycle; + private TextView tvDutyCycleValue; + private int currentDutyCyclePercent = 30; // 默认占空比30% + private static final int PWM_PERIOD = 1000000; // 1ms周期 // 动画管理器 private RobotFaceAnimationManager animationManager; + private boolean isCalibrating = false; + private boolean isForwardCalibration = false; + private boolean isReverseCalibration = false; + private Runnable wearDetectionRunnable = new Runnable() { @Override @@ -131,6 +135,43 @@ public class MainActivity extends AppCompatActivity implements WebSocketManager. // 初始化UI控件 ivFace = (ImageView) this.findViewById(R.id.iv_face); +// btnRotateForward = (Button) this.findViewById(R.id.btn_rotate_forward); +// btnRotateReverse = (Button) this.findViewById(R.id.btn_rotate_reverse); +// seekBarDutyCycle = (SeekBar) this.findViewById(R.id.seekbar_duty_cycle); +// tvDutyCycleValue = (TextView) this.findViewById(R.id.tv_duty_cycle_value); + +// // 设置占空比调整监听器 +// seekBarDutyCycle.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { +// @Override +// public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { +// currentDutyCyclePercent = progress; +// tvDutyCycleValue.setText("占空比: " + progress + "%"); +// } +// +// @Override +// public void onStartTrackingTouch(SeekBar seekBar) {} +// +// @Override +// public void onStopTrackingTouch(SeekBar seekBar) {} +// }); +// +// // 设置正转按钮点击监听器 +// btnRotateForward.setOnClickListener(v -> { +// if (motorController != null) { +// int dutyCycle = (int) (PWM_PERIOD * currentDutyCyclePercent / 100.0); +// motorController.rotateReverse(PWM_PERIOD, 0); // 确保反转PWM关闭 +// motorController.rotateForward(PWM_PERIOD, dutyCycle); +// } +// }); +// +// // 设置反转按钮点击监听器 +// btnRotateReverse.setOnClickListener(v -> { +// if (motorController != null) { +// int dutyCycle = (int) (PWM_PERIOD * currentDutyCyclePercent / 100.0); +// motorController.rotateForward(PWM_PERIOD, 0); // 确保正转PWM关闭 +// motorController.rotateReverse(PWM_PERIOD, dutyCycle); +// } +// }); // 初始化动画管理器 animationManager = new RobotFaceAnimationManager(this, ivFace); @@ -155,22 +196,18 @@ public class MainActivity extends AppCompatActivity implements WebSocketManager. handler.post(faceAnimationRunnable); }).start(); + + // 检查并请求必要的权限 checkAndRequestPermissions(); + // 隐藏状态栏和导航栏 hideSystemBars(); // 初始化设备管理器 initDeviceManager(); - //testMotorControl(); -// // 延迟2秒后开始测试,确保设备管理器初始化完成 -// handler.postDelayed(new Runnable() { -// @Override -// public void run() { -// startProtocolTests(); -// } -// }, 2000); + testMotorControl(); //xiaozhi initAudio(); @@ -285,6 +322,16 @@ public class MainActivity extends AppCompatActivity implements WebSocketManager. } + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + Log.d(TAG, "keyCode: "+ keyCode); + if (keyCode == HEAD_TOUCH_KEY) { + // 处理返回键按下事件 + Log.d(TAG, "触摸了机器人的头"); + return true; // 返回true表示事件已被处理 + } + return super.onKeyDown(keyCode, event); // 让系统继续处理其他按键事件 + } private void startProtocolTests() { LogManager.d(TAG, "开始协议测试..."); @@ -389,6 +436,18 @@ public class MainActivity extends AppCompatActivity implements WebSocketManager. gpioManager = null; } + // 中断电机控制线程 + if (motorControlThread != null && motorControlThread.isAlive()) { + try { + motorControlThread.interrupt(); + motorControlThread.join(1000); // 等待线程结束,最多等待1秒 + LogManager.d(TAG, "电机控制线程已中断"); + } catch (InterruptedException e) { + LogManager.e(TAG, "等待电机控制线程结束时被中断"); + } + motorControlThread = null; + } + // 释放电机控制器资源 if (motorController != null) { try { @@ -452,7 +511,17 @@ private void testMotorControl() { return; } - new Thread(() -> { + // 如果之前的线程还在运行,先中断它 + if (motorControlThread != null && motorControlThread.isAlive()) { + motorControlThread.interrupt(); + try { + motorControlThread.join(1000); // 等待线程结束,最多等待1秒 + } catch (InterruptedException e) { + LogManager.e(TAG, "等待之前的电机控制线程结束时被中断"); + } + } + + motorControlThread = new Thread(() -> { try { // 打开电机 LogManager.d(TAG, "打开电机"); @@ -462,44 +531,52 @@ private void testMotorControl() { } // 设置PWM参数 final int period = 1000000; - final int dutyCycle = 1000000; // 使用90%的占空比,避免duty_cycle等于period - - Thread.sleep(10000); -// LogManager.d(TAG, "电机正转"); + final int fdutyCycle = 1000000; // 使用90%的占空比,避免duty_cycle等于period + final int rdutyCycle = 1000000; // 使用90%的占空比,避免duty_cycle等于period +// Thread.sleep(2000); // motorController.rotateReverse(period, 0); // 确保反转PWM关闭 // if (!motorController.rotateForward(period, dutyCycle)) { // LogManager.e(TAG, "电机正转失败"); // } +// Thread.sleep(2000); +// // 电机反转 +// motorController.rotateForward(period, 0); +// if (!motorController.rotateReverse(period, dutyCycle)) { +// LogManager.e(TAG, "电机反转失败"); +// } + // 循环20次正反转 - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 10000; i++) { LogManager.d(TAG, "开始第" + (i + 1) + "次正反转测试"); // 电机正转 LogManager.d(TAG, "电机正转"); motorController.rotateReverse(period, 0); // 确保反转PWM关闭 - if (!motorController.rotateForward(period, dutyCycle)) { + if (!motorController.rotateForward(period, fdutyCycle)) { LogManager.e(TAG, "电机正转失败"); break; } // 等待100ms - Thread.sleep(100); + Thread.sleep(120); // 停止正转 motorController.rotateForward(period, 0); - + Thread.sleep(1000); // 电机反转 LogManager.d(TAG, "电机反转"); - if (!motorController.rotateReverse(period, dutyCycle)) { + if (!motorController.rotateReverse(period, rdutyCycle)) { LogManager.e(TAG, "电机反转失败"); break; } // 等待100ms - Thread.sleep(100); + Thread.sleep(40); // 停止反转 motorController.rotateReverse(period, 0); + + Thread.sleep(1000); } // 测试完成,关闭电机 @@ -513,7 +590,8 @@ private void testMotorControl() { LogManager.e(TAG, "电机测试异常: " + e.getMessage()); motorController.turnOffMotor(); } - }).start(); + }); + motorControlThread.start(); } @Override diff --git a/app/src/main/java/com/ismart/ib86/feature/motor/MotorController.java b/app/src/main/java/com/ismart/ib86/feature/motor/MotorController.java index 6550c05..b7577e3 100644 --- a/app/src/main/java/com/ismart/ib86/feature/motor/MotorController.java +++ b/app/src/main/java/com/ismart/ib86/feature/motor/MotorController.java @@ -24,7 +24,7 @@ public class MotorController { // PWM路径常量 private static final String PWM_FORWARD_PATH = "/sys/class/pwm/pwmchip0/pwm0/"; - private static final String PWM_REVERSE_PATH = "/sys/class/pwm/pwmchip1/pwm0/"; + private static final String PWM_REVERSE_PATH = "/sys/class/pwm/pwmchip2/pwm0/"; private static final String PWM_PERIOD_FILE = "period"; private static final String PWM_DUTY_CYCLE_FILE = "duty_cycle"; private static final String PWM_ENABLE_FILE = "enable"; diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index bb0316c..2279dc0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,9 +4,72 @@ android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="#000000" tools:context=".MainActivity"> + + + + + + + +