资讯动态

闲置安卓手机跑 openclaw:抓娃娃机控制移植与后台保活

发布时间:2026/10/29 15:59:01 来源:尧图企业网站定制
把 openclaw-android 这套组合跑起来我前前后后折腾了差不多三个周末中间换过两台旧手机、烧过一根 OTG 转接线、被 Android 12 的后台清理机制坑到怀疑人生。这个项目本身是一套开源的抓娃娃机claw machine控制系统原本的形态是跑在树莓派上用 Python 写服务端、用摄像头做视觉识别、用 GPIO 直接驱动舵机。而 openclaw-android 要干的事就是把这套控制逻辑整体挪到一台安卓手机上让手机同时充当计算单元、显示终端和网络控制台。听起来很美好实际上每一步都在跟安卓的封闭性较劲。这篇内容适合三类人看手上有闲置旧手机、想拿它做点硬件控制项目的人已经在树莓派上跑通过类似方案、想换个更轻的载体的人以及纯粹想搞清楚安卓到底能不能当一个正经的嵌入式主控的人。下面我按自己实际的落地顺序讲不讲理论推演只讲哪一步做了什么、为什么这么做、卡住的时候怎么绕过去。1. 把 openclaw 挪到安卓手机上先算清楚这笔账动手之前我建议你先花十分钟想清楚动机因为这套移植不是没有代价的。我最初的想法很朴素手边有两台淘汰的安卓机屏幕完好、电池还能撑三小时、WiFi 模块正常工作而一块能跑图形界面的树莓派套件加屏幕加电源加外壳成本并不低还得等货。手机是现成的插上就能用这笔账怎么算都划算。但真正开始动手之后你会发现省下来的硬件成本会以另一种形式还回去——你的时间成本会大幅上升因为安卓系统在设计之初就没打算让你在它上面跑一个长期驻留的服务进程。1.1 一台闲置安卓机补上了树莓派的哪些短板先说优势这部分是实打实的。第一是供电的完整性手机自带电池和电源管理芯片相当于天然带了一个 UPS。抓娃娃机这种设备最怕的就是运行中途断电服务进程崩了、状态丢失了机械爪停在半空下次上电还得手动复位。手机不会拔掉充电线它还能撑一段时间检测到外部供电恢复后自动继续充电整个过程服务不中断。第二是人机界面树莓派要么接 HDMI 显示器要么 SSH 上去看命令行而手机自带一块触摸屏服务跑起来之后直接在本机浏览器打开控制页面调参数、看画面、手动点按钮测试体验好太多。第三是体积和集成度手机一体化封装没有裸露的排线、没有松动的 Micro HDMI塞进机器外壳里非常省空间。代价也很明确。安卓是一个为前台应用设计的操作系统它假设用户会不断地和应用交互一旦某个进程长时间不在前台系统就会毫不客气地把它回收掉。而 openclaw 的服务端恰恰是一个需要 7×24 小时静默运行的守护进程这个矛盾贯穿整个部署过程后面第 6 章会专门讲怎么和它周旋。另外手机没有 GPIO 排针没有标准 USB 主机口只有 OTG也没有可以被 Linux 直接识别的摄像头设备节点这三条限制决定了后面所有的架构改造。1.2 移植前必须确认的三个硬约束在下载任何安装包之前我建议你先做三件事能省掉后面大量的返工。确认系统版本和厂商定制程度。我用第一台手机试的时候踩了个大坑那台机器是某厂商深度定制的系统后台管理策略极其激进即使把应用加进电池优化白名单、锁住最近任务它依然会在息屏后十几分钟内把进程杀掉。后来换成一台接近原生系统的旧机型同样配置下能连续跑十几个小时不掉线。所以如果你手上有得选优先挑系统改动少的机器。确认 OTG 是否可用、供电能力如何。有些机型的 OTG 口供电非常弱接一个 USB 转串口模块勉强能识别再接一个带供电的 USB Hub 就直接识别不到了。我的做法是先用一个最简单的 U 盘插上去测能稳定识别再往下走。确认电池健康度。长期插着充电线运行电池一直处于满电状态对老电池不太友好鼓包的风险是真实存在的。我第二台机器就是常年插电三个月后电池明显鼓了。如果打算长期跑建议把后盖打开把电池拆掉用稳压电源直接给主板供电或者至少不要把机器放在无人看管的地方长时间充电。这三条确认完再往下走心里就有底了。2. 在手机里养出一个能跑 Python 的环境整个方案的基础是一个终端模拟器加上一套 Linux 用户态环境我用的方案是在手机上装一个终端模拟器应用它会在应用私有目录里构建一个独立的文件系统里面可以安装 Python、编译器、各类库跟安卓系统本身互不干扰。这一章讲的就是怎么把这个环境搭稳。2.1 终端环境的版本选择与初始换源第一件事是不要用应用商店里那个版本。商店版本往往更新滞后而且部分机型上存在签名和存储权限问题。我建议从项目自己的发布渠道获取安装包版本号尽量选近半年内的。装完之后第一件事是执行存储授权命令让它能够在共享存储里读写文件否则你后面想把日志、图片导出来会很麻烦。初始化的时候有两件事必须做。一是更新包索引二是换源。默认的软件源在境外拉一个几百兆的编译工具链能等到你放弃。换成就近镜像之后同样的包可能几十秒就下完了。pkg update pkg upgrade -y pkg install -y python python-pip clang cmake make pkg-config git这里有个细节pkg upgrade之后如果提示配置文件冲突选择保留本地版本即可不要盲目覆盖。我曾经因为一路选覆盖把源配置冲掉了后面所有的包都拉不下来排查了半小时才发现是配置文件的问题。另外环境装好之后建议立刻做一次快照备份把整个 home 目录打包后面装崩了直接回滚比重新配一遍快得多。2.2 依赖清单哪些能用包管理器装哪些必须放弃openclaw 本体是 Python 写的依赖大致分三类网络服务框架、串口通信库、图像处理库。前两类很轻松第三类是整个部署里最麻烦的部分。依赖类型具体包推荐安装方式说明Web 服务flask、werkzeugpip 安装纯 Python无编译秒装串口通信pyserialpip 安装纯 Python可以放心使用数值计算numpy包管理器安装pip 编译版本在手机上几乎跑不通图像处理opencv包管理器安装必须用预编译版本不要 pip图像采集系统相册/摄像头 API通过命令行工具调用无标准 V4L2 设备节点关键结论numpy 和 opencv 一定要用包管理器提供的预编译包绝对不要用 pip 去装。原因很实在。pip 安装opencv-python的时候PyPI 上根本没有为安卓平台提供预编译 wheel它会退回到源码编译而要编译完整的 OpenCV需要拉下几百兆的源码、需要一大堆图像编解码库的头文件、需要至少一个小时的编译时间最后大概率还会因为缺少某个系统库而失败。我在第一台机器上就干过这事编译到 73% 报错退出白等了两小时。改用包管理器之后pkg install -y python-numpy python-opencv libjpeg-turbo libpng pip install flask pyserial两分钟搞定。装完立刻验证一下python -c import numpy, cv2, serial, flask; print(numpy.__version__, cv2.__version__)能正常打印版本号环境这关就过了。2.3 编译类依赖翻车的三种典型现场即便走了预编译包的路线你还是有可能遇上需要本地编译的场景比如你想装某个小众的协议库。我遇到过三种情况都总结成了固定的处理套路。第一种是缺少头文件报错信息里出现fatal error: xxx.h: No such file or directory。这时候不要急着去搜直接把报错里的文件名去掉.h和版本号用pkg search搜一下通常能找到对应的-dev包装上再试。第二种是链接阶段找不到库报错类似undefined reference to。这多半是因为库装了但路径没被识别需要手动指定环境变量。我一般会在 shell 配置里加一行把库目录和头文件目录显式指出来虽然不够优雅但很省事。第三种最麻烦是编译过程中被系统杀掉。手机上编译大一点的 C 扩展内存占用很容易冲到 1G 以上系统一看后台进程占这么多内存直接就给你终止了终端上只显示一个Killed没有任何其他信息。我第一次遇到的时候以为是代码问题反复排查了半天。解决办法是关掉所有其他应用先执行一次内存清理然后分步编译别用一条命令跑到底。提示所有涉及编译的操作尽量在充电状态下、屏幕常亮的情况下做并且把终端应用锁在最近任务列表里。中途切出去回个消息很可能就前功尽弃。3. 没有 GPIO 怎么办USB 转串口加下位机的两级架构这是整个移植里最核心的一次架构改造也是很多人卡住的地方。原版 openclaw 在树莓派上跑的时候代码里是直接操作 GPIO 引脚输出 PWM 信号驱动舵机的一行GPIO.output(pin, True)就把事办了。安卓手机没有这个能力无论你怎么装库都变不出物理引脚来。所以必须换思路。3.1 为什么必须改成手机发指令、下位机执行最直接的替代方案是通过 OTG 接一个 USB 转串口模块再接一块微控制器板让微控制器负责真正驱动舵机、读取限位开关手机只负责算和说。这就是典型的两级架构上位机手机负责视觉识别、状态机、Web 界面、用户交互下位机微控制器负责实时性要求高的 PWM 输出和传感器采样。这个拆分并不是被迫妥协反而带来了实际好处。舵机控制对时序要求很高PWM 信号的抖动会直接体现在机械爪的动作上爪子会抖、会不到位。而安卓系统本身不是一个实时操作系统Python 解释器还有 GC 停顿让手机直接产生稳定的 PWM 波形基本不现实。把这块交给一个跑裸机循环的微控制器时序稳定性反而比原版树莓派方案更好。我在实测中把爪子的定位重复精度做到了肉眼几乎看不出偏差这是纯软件方案很难达到的。改造的代价是你要重新定义通信协议。我在上位机侧把原来直接调 GPIO 的函数全部替换成串口写指令指令设计得非常简单用文本行协议每条指令以换行符结尾下位机解析后执行并回一行状态上位机 - 下位机 CLAW_OPEN\n 下位机 - 上位机 OK 1\n 上位机 - 下位机 MOVE_X 320\n 下位机 - 上位机 OK 2\n 上位机 - 下位机 STATUS\n 下位机 - 上位机 X320 Y180 CLAWOPEN LIMIT0\n文本协议的好处是可读性极强出问题的时候直接把串口日志打印出来看一眼就知道卡在哪一步。缺点是带宽利用率低但对这个场景完全够用一秒钟几十条指令已经是极限了。3.2 拿到串口设备节点的完整流程安卓上访问 USB 设备比 Linux 麻烦得多因为普通应用没有直接打开/dev/ttyUSB0的权限。这里必须借助系统提供的 USB 访问工具通过文件描述符的方式把设备句柄传递给 Python。完整流程是这样的# 1. 安装必要组件 pkg install -y termux-api libusb # 2. 列出当前接入的 USB 设备 termux-usb -l # 输出类似/dev/bus/usb/001/003 # 3. 用指定程序打开该设备程序会收到一个文件描述符 termux-usb -r -e python claw_bridge.py /dev/bus/usb/001/003被调起的程序会通过环境变量或命令行参数拿到一个已经打开的 fd 编号然后把这个 fd 直接包装成 pyserial 的串口对象import os, sys, serial # fd 由 termux-usb 通过参数传入 fd int(sys.argv[1]) ser serial.Serial() ser.baudrate 115200 ser.bytesize 8 ser.parity N ser.stopbits 1 ser.timeout 0.2 ser._socket None ser.fd fd # 关键直接复用已授权的文件描述符 ser.is_open True ser.write(bSTATUS\n) print(ser.readline().decode().strip())这段代码看着不优雅但它是目前最省事的办法。只要拿到了 fd后面的读写和普通串口完全一样。注意每次重新插拔 USB 设备设备路径和 fd 都会变所以这套逻辑必须写成自动发现的形式不能把/dev/bus/usb/001/003硬编码在脚本里。我的做法是启动时先跑一次设备列表匹配到目标设备的 VID/PID 之后再发起授权匹配不到就每隔两秒重试一次。3.3 下位机固件与接线自检清单下位机那边我建议先用最简版本跑通再说不要一上来就上复杂的运动学算法。最小可用固件只需要做四件事上电初始化所有舵机到中位、循环读取串口指令、按指令驱动对应舵机、回传状态。整个固件不到两百行逻辑清晰出了问题也好定位。接线自检我总结了一个固定顺序每次改动硬件后都按这个顺序走一遍先单独接舵机电源确认舵机能动再接信号线确认微控制器能输出 PWM然后接限位开关用串口打印确认开关状态随物理按压变化最后接串口通信线确认双向收发正常。这个顺序的意义是每次只引入一个变量一旦出问题你能立刻知道是哪一环。我在这个环节最惨的一次经历是爪子动作到一半突然全停重插 USB 才好。折腾了很久才发现是 OTG 口供电不足舵机启动瞬间的电流冲击把 USB 转串口模块拉挂了。后来换了一个带外部供电的 USB Hub把微控制器和串口模块都接到 Hub 上问题彻底消失。这个坑很隐蔽因为表现上是软件死机实际上是硬件掉电。4. 摄像头才是移植路上最大的拦路虎如果你以为硬件控制是最难的部分那说明你还没试过在安卓上读摄像头。这一章我要重点讲因为这几乎是每个想在这条路上走下去的人都会撞墙的地方。4.1 安卓摄像头不是 /dev/video0在 Linux 环境里摄像头就是/dev/video0一行cv2.VideoCapture(0)就能拿到画面。安卓完全不是这么设计的。安卓的摄像头由相机服务统一管理应用必须通过系统提供的 API 去访问这个 API 是 Java/Kotlin 层的Python 根本够不着。你去/dev目录下翻能找到的只有一堆和摄像头无关的节点。我一开始不信邪试了cv2.VideoCapture(0)、cv2.VideoCapture(-1)、cv2.VideoCapture(/dev/video0)全部返回空帧或者直接报错。后来查了很多资料才确认这条路在非 root 的情况下走不通。即使 root 了也不一定能稳定工作因为安卓的相机 HAL 层和标准 V4L2 差距很大。所以必须换方案。我实际试过三条路最后选了第二条。方案实现方式帧率稳定性适用场景命令行拍照定时调用系统相机命令约 0.5 帧高对实时性要求低本机视频流相机应用推本地流Python 拉流15-25 帧中高需要实时识别原生接口打通自定义封装层30 帧低需要深度定制4.2 本机视频流回环方案的实际配置最终我采用的是手机自己推流给自己的思路装一个能把摄像头画面转成本地视频流的应用让它以 RTSP 或 MJPEG 的形式发布在回环地址上然后 Python 端用 OpenCV 去拉这个流。整个数据不出设备全在 127.0.0.1 上跑延迟可以压得很低。配置分三步。第一步在视频流应用里设置分辨率、码率和帧率我建议先用640×480、15 帧、码率 1Mbps这组保守参数跑通别一上来就上 1080p。第二步是启动服务记录下它监听的端口通常是类似rtsp://127.0.0.1:8554/preview这样的地址。第三步是 Python 端把原来的摄像头初始化改成拉流import cv2 STREAM_URL rtsp://127.0.0.1:8554/preview cap cv2.VideoCapture(STREAM_URL, cv2.CAP_FFMPEG) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 关键减小缓冲降低延迟 if not cap.isOpened(): raise RuntimeError(拉流失败先确认视频流服务已经启动) while True: ok, frame cap.read() if not ok: # 断流后自动重连别让整个服务挂掉 cap.release() cap cv2.VideoCapture(STREAM_URL, cv2.CAP_FFMPEG) continue # 后续识别逻辑...这里CAP_PROP_BUFFERSIZE设为 1 是个很重要的经验。默认缓冲会缓存好几帧导致你看到的画面比实际延迟一秒以上对于抓取这种需要精确对位的事情一秒延迟足够让爪子抓空。设成 1 之后延迟能压到两百毫秒以内。4.3 分辨率、帧率与识别准确率的三方拉扯这块我调了很久最后总结出一条经验分辨率不是越高越好帧率也不是越高越好真正决定成败的是两者的乘积能不能被手机的 CPU 吃下去。我的实测数据是640×480 加 15 帧单帧识别耗时约 60 毫秒CPU 占用率在 40% 左右服务能长时间稳定运行1280×720 加 25 帧单帧识别耗时涨到 180 毫秒CPU 占用率冲到 85%几分钟后手机开始明显发热然后系统降频帧率掉到个位数识别就完全没法用了。所以最终我锁死在 640×480、15 帧这组参数上识别准确率对于抓取定位来说完全够用。还有一个容易被忽略的点识别算法本身要做减法。原版用的是一个比较重的检测流程在树莓派上跑着还行挪到手机上就必须精简。我的做法是把检测区域先裁出来只对画面中间那一块做处理分辨率再降一半速度立刻翻倍。原理很简单反正爪子只在中部区域活动边缘的画面信息对定位毫无价值白白消耗算力。5. 服务起来之后局域网联调与端口那些事前面几章把环境和硬件都打通了这一章讲怎么把服务真正跑起来并且能从别的设备访问到。别看这一步好像很简单实际上有几个安卓特有的坑。5.1 监听地址和端口的修改要点原版项目通常是按本机访问设计的服务监听在127.0.0.1上端口可能是 5000。搬到手机上之后你大概率希望用电脑或者平板来操作那么必须做两处改动。第一处是监听地址改成0.0.0.0让它接受来自局域网内其他设备的连接。第二处是端口号避开 1024 以下的特权端口。安卓上普通应用是没有权限绑定低端口的如果你照抄某个教程用了 80 端口启动时会直接报权限错误。我用的是 8080一个安全又好记的选择。if __name__ __main__: app.run( host0.0.0.0, port8080, threadedTrue, debugFalse )threadedTrue这个参数必须加上。因为服务里同时有视频流和状态轮询两个请求单线程模式下浏览器打开页面会一直转圈因为视频流把线程占死了状态请求永远排不上队。我第一次跑起来的时候就是这个问题页面白屏控制台一直显示等待响应查了半天才发现是这个参数没开。另外debugFalse也别忘。调试模式下 Flask 会启动自动重载器监视文件变化然后重启进程在手机上这个机制非常容易和后台管理冲突表现为服务莫名其妙重启。生产环境一定要关掉。5.2 手机端与电脑端的双向验证步骤服务起来之后不要急着开浏览器按顺序验证出问题好定位。第一步在手机自己的浏览器里访问http://127.0.0.1:8080能打开说明服务和端口没问题。第二步查手机的局域网地址在电脑浏览器里访问同样的路径把 IP 换掉。打不开的话先检查两台设备是不是在同一个网段再看手机是不是开了隔离模式部分路由器的访客网络会隔离设备。第三步打开具体功能页面看视频流能不能正常显示点几个控制按钮看串口指令有没有下发出去。我遇到过两次局域网访问不通的情况。一次是手机连的是 5G 频段电脑连的是 2.4G 频段路由器做了频段隔离两台设备互相 ping 不通改到同一频段就好了。另一次是手机在息屏后 WiFi 进入了省电模式IP 地址还在但连接无响应这个问题比较隐蔽需要在系统的 WiFi 高级设置里把息屏保持连接打开。5.3 日志落盘与远程查看的土办法安卓上最难受的一点是服务崩了你看不到任何现场。终端应用一切到后台输出就断了回来之后只看到一片空白。所以必须把日志写到文件里。我的做法很简单启动脚本里把标准输出和标准错误全部重定向到文件按天切分LOG_DIR$HOME/claw_logs mkdir -p $LOG_DIR STAMP$(date %Y%m%d_%H%M%S) nohup python main.py $LOG_DIR/run_$STAMP.log 21 echo $! $HOME/claw.pid想在电脑上看日志的话最简单的办法是在服务里加一个只读的日志查询页面或者用手机上的文件管理器把日志文件通过共享存储暴露出来再从电脑访问。我用的是后一种手机上装个支持局域网共享的文件管理应用指定日志目录电脑上映射成网络驱动器用任意文本编辑器实时查看。虽然土但是极其好用比任何花哨的日志系统都直接。提示日志文件一定要做体积控制。手机上跑一周日志能涨到几百兆占满存储之后服务会以各种奇怪的方式失败。我在启动脚本里加了一条按天清理的命令只保留最近七天的日志。6. 扛住 Android 的后台清理才谈得上长期运行前面五章解决的是能不能跑这一章解决的是能不能一直跑。说实话这部分花了我最多时间因为它没有任何标准答案不同的机型、不同的系统版本表现完全不一样。6.1 唤醒锁、电池优化白名单与厂商自启权限首先要理解安卓的省电逻辑。系统默认假设后台应用是不重要的所以会做两件事一是在息屏后限制 CPU 唤醒二是定期清理长时间不在前台的进程。你的服务要活下来必须逐层突破这些限制。第一层是唤醒锁。终端应用本身提供了这个功能在它的通知栏里有一个获取唤醒锁的选项点一下系统就不会在息屏后挂起这个进程。这一步是基础不做的话息屏几分钟服务就停了。第二层是电池优化白名单。进系统设置的应用管理找到终端应用把电池优化改成不限制或者允许后台活动。不同系统的入口名字不一样有的叫省电策略有的叫后台运行权限但目的都一样。第三层是厂商的自启管理。部分定制系统有独立的自启动管理面板默认会阻止所有第三方应用自启需要手动把终端应用和它的配套插件加白名单。这一层最容易被忽略也最坑因为前面两层都做对了重启手机后服务还是没起来就是卡在这里。这三层做完我在原生系统上能做到连续运行十几个小时不掉线。但如果你用的是定制比较深的系统可能还需要额外把应用锁在最近任务列表里防止一键清理把它带走。6.2 Android 12 之后那个要命的进程数限制这是我在整个项目里踩得最深的一个坑值得单独拿出来讲。从 Android 12 开始系统引入了一个针对幽灵进程的监控机制。它的本意是防止应用偷偷 fork 出一堆子进程消耗资源但对终端模拟器这类应用来说这是一个灾难。终端里跑的 Python 服务、拉流进程、守护脚本全部会被算作子进程一旦数量超过阈值通常是 32 个系统会静默地把它们批量杀掉日志里什么都不留。我第一次遇到的时候服务跑了四十分钟突然没了没有任何报错重启之后又能跑四十分钟非常规律像是有个定时器。排查过程是这样的先怀疑是内存泄漏挂了监控脚本记录内存占用发现被杀的时候内存才用了 300M排除再怀疑是某个库崩溃把标准错误重定向到文件结果被杀的瞬间日志直接断掉连异常都没打出来说明不是进程内崩溃然后怀疑是系统清理把电池优化的所有限制都关了还是四十分钟最后是在系统日志里翻到了一条和进程数相关的记录才锁定了这个机制。解决办法有两条。如果你能连电脑调试用调试命令把这个监控关掉是最干净的adb shell settings put global settings_enable_monitor_phantom_procs false这条命令不需要 root但需要你在电脑上装好调试工具、手机开启调试模式并授权。设置之后重启手机生效服务能稳定跑下去。如果实在没有电脑可用那就只能从减少子进程数量入手把能合并的进程合并比如把拉流和识别放在同一个进程里做守护脚本用轮询而不是再起一个子进程尽量避免在服务里调用外部命令。6.3 崩溃自恢复与开机自启即便做了上面所有措施服务还是有可能因为各种原因挂掉。所以必须要有一层自恢复机制。我的做法是写一个极简的守护循环逻辑就是检查进程是否存活不存活就重启每三十秒检查一次。这个脚本本身也可能被杀所以它需要和唤醒锁配合使用。另外重启操作要有次数限制比如十分钟内重启超过五次就停下并写日志避免陷入无限重启的死循环把手机拖垮。#!/data/data/com.termux/files/usr/bin/bash MAX_RESTART5 WINDOW600 count0 start_ts$(date %s) while true; do if [ -f $HOME/claw.pid ] kill -0 $(cat $HOME/claw.pid) 2/dev/null; then sleep 30 continue fi now$(date %s) if [ $((now - start_ts)) -gt $WINDOW ]; then count0 start_ts$now fi count$((count 1)) if [ $count -gt $MAX_RESTART ]; then echo $(date) 重启过于频繁停止守护 $HOME/claw_logs/guard.log sleep 300 count0 continue fi echo $(date) 检测到服务退出正在重启 $HOME/claw_logs/guard.log bash $HOME/start_claw.sh sleep 5 done开机自启则需要装终端应用的启动插件把守护脚本放到它约定的启动目录下命名成.sh结尾的可执行脚本。要注意的是这个目录下的脚本是在系统启动完成后由插件自动执行的如果你的手机有锁屏密码某些机型需要先解锁一次才会触发这一点在说明书里通常不会写但实测确实存在。7. 一份可以照着抄的落地清单与踩坑记录最后这一章不讲原理只把我实际用的目录结构、参数和经验整理出来你可以直接照着搭。7.1 目录结构与启动参数~/claw/ ├── main.py # 服务主入口 ├── claw_bridge.py # 串口桥接层 ├── vision.py # 图像识别模块 ├── start_claw.sh # 启动脚本 ├── guard.sh # 守护循环 ├── config.py # 参数配置 └── logs/ # 日志目录 ├── run_20240101.log └── guard.log配置参数我建议集中放在一个文件里别散落在各处。以下是我实测能稳定运行的组合参数取值说明视频流分辨率640×480再高 CPU 扛不住视频流帧率15与识别耗时匹配串口波特率115200指令量小够用且稳定串口超时0.2 秒太短容易读不全太长卡主线程服务端口8080避开特权端口守护检查间隔30 秒太频繁会额外耗电日志保留天数7 天控制存储占用7.2 供电、发热与串口掉线供电这块我要多说两句因为它是最容易被低估的环节。手机本身要充电OTG 口要带串口模块和微控制器如果再加上舵机总电流很容易超出 OTG 口的供给能力。表现就是一切正常但偶尔串口通信中断重插才好。这个问题在软件层面完全看不出来日志里只会显示读写超时。解决办法是用带外部供电的 USB Hub把微控制器和串口模块接到 Hub 上Hub 单独接电源手机只负责数据。这样供电压力和手机彻底解耦稳定性提升立竿见影。发热同样要重视。手机跑视频解码加图像识别长时间工作温度能到四十多度一旦触发降频帧率断崖式下跌识别就跟不上了。我的处理是给机器外壳开了散热孔内部贴了一块小散热片对着主板背面实测表面温度能降五六度够用了。7.3 我的整体时间投入与几个建议从零到能稳定运行我大概花了二十多个小时其中真正写代码的时间不到三小时剩下的全在和环境、和系统策略、和硬件供电较劲。如果你准备动手我给出三条建议。第一先用最小的功能跑通全链路再逐层加复杂度。我的顺序是先让服务在手机上启动、浏览器能打开页面再打通串口能点按钮让舵机动一下最后才接视频流做识别。每一步都确认可用之后再往下走出问题的时候范围很小好定位。第二给每个环节写一个独立的自检脚本。串口自检、视频流自检、磁盘空间自检、内存占用自检。这些东西加起来不到一百行但能让你在出问题的时候三十秒内知道是哪一环坏了而不是对着一堆日志瞎猜。第三别追求一次到位。我在第一台手机上折腾了整整两天最后发现是那台机器的系统策略太激进根本不适合这个用途。换一台机器同样的配置半小时就跑起来了。有时候换硬件比调软件划算得多。现在这套方案在我这儿已经跑了小半年中间因为一次系统更新重启过一遍其他时间都稳定。要说还有什么不满意的就是视频延迟这一块始终没法压到一百毫秒以内对于慢速抓取没问题但如果想把动作做得更快更狠估计还是得回到更底层的方案上去。后面如果有进展我再单独写一篇。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑