OpenHarmony 项目实战:基于全志 XR806 实现的简易四足行走机器狗
本文整理自:https://bbs.aw-ol.com/topic/932/
作者 @ 堇花还没开吗
小米在2021年发布的自研四足仿生机器人——CyberDog,使得“仿生机器人”这个话题 再次站在风口之上 ,伴随芯片、舵机、减速器等核心部件的发展,也期待更多更“生动”的“仿生机器人”出现 ,全志XR806是一款支持WiFi和BLE的芯片可满足智能机器人等领域的无线连接需求,今天就先带大家看一款基于全志XR806开源鸿蒙开发板做的四足行走机器狗。
一、机器狗外观图
二、PCA9685开发流程
狗子身上有12个舵机,一条腿接3个舵机,连接到一个pca9685舵机驱动上,舵机驱动通过I2C与XR806通信,XR806有两个I2C接口,我主要是用第1个(B14, B15),通过控制PCA9685上的寄存器来简介控制舵机。
pca9685参数:
- I2C接口,支持高达16路PWM输出,每路12位分辨率(4096级);
- 内置25MHz晶振,可不连接外部晶振,也可以连接外部晶振,最大50MHz;
- 支持2.3V-5.5V电压,最大耐压值5.5V,逻辑电平3.3V;
- 具有上电复位,以及软件复位等功能。
1. pca初始化
首先要进行i2c初始化:
i2c_init(i2c_id);
导入相关库:
#include "driver/chip/hal_i2c.h" #define i2c_id 1 # 使用第1个i2c
i2c初始化函数:
void i2c_init(unsigned int id){ I2C_InitParam initParam; initParam.addrMode = I2C_ADDR_MODE_7BIT; initParam.clockFreq = 40000; if (HAL_I2C_Init(id, &initParam) != HAL_OK) { printf("i2c init fail!\n"); while(1); } else { printf("i2c init success!\n"); } }
主要是调用HAL_I2C_Init函数对第1个i2c接口进行初始化。
初始化pca9685:
pca9685_init(60);
pca9685_init函数:
void pca9685_init(float hz) { pca_write(pca_mode1, 0x0); pca_setfreq(hz); OS_MSleep(500); }
2. pca操作
1. pca9685写寄存器
void pca_write(uint8_t reg_addr, uint8_t data) { uint8_t buf[1]; buf[0] = data; HAL_I2C_Master_Transmit_Mem_IT(i2c_id, pca_adrr, reg_addr, I2C_MEMADDR_SIZE_8BIT, buf, 1); }
2. pca9685读寄存器
uint8_t pca_read(uint8_t reg_addr) { uint8_t buf[1]; HAL_I2C_Master_Receive_Mem_IT(i2c_id, pca_adrr, reg_addr, I2C_MEMADDR_SIZE_8BIT, buf, 1); return buf[0]; }
3. pca9685设置频率
void pca_setfreq(float freq) { uint8_t prescale,old_mode,new_mode; double prescaleval; freq *= 0.92; prescaleval = 25000000; prescaleval /= 4096; prescaleval /= freq; prescaleval -= 1; prescale =(uint8_t)(prescaleval + 0.5f); old_mode = pca_read(pca_mode1); new_mode = (old_mode & 0x7F) | 0x10; pca_write(pca_mode1, new_mode); pca_write(pca_pre, prescale); pca_write(pca_mode1, old_mode); OS_MSleep(2); pca_write(pca_mode1, old_mode | 0xa1); }
这里的代码不像读函数和写函数一样好理解,主要是一般情况下,在用pca9685内置晶振,为25MHZ,通过配置PRE_SCALE寄存器进行配置。如果在舵机控制中,采用内置晶振,取osc_clock=25000000,update_rate=50(舵机控制频率50Hz)。
而且在写PRESCALE寄存器的时候,要先设置为Sleep模式,也就是将mode1寄存器的SLEEP标志位设置为1,具体可参考我上面写的代码。
3. pca设置pwm
void pca_setpwm(uint8_t num, uint32_t on, uint32_t off) { pca_write(LED0_ON_L+4*num,on); pca_write(LED0_ON_H+4*num,on>>8); pca_write(LED0_OFF_L+4*num,off); pca_write(LED0_OFF_H+4*num,off>>8); }
pwm通道寄存器如下图:
由图可知,对于每一个通道,有4个寄存器,在设置PWM占空比的时候,首先配置舵机的示例如下图所示(ON < OFF的情况):
核心代码:
#include <stdio.h> #include "ohos_init.h" #include "kernel/os/os.h" // #include "iot_i2c.h" #include "driver/chip/hal_i2c.h" #include "iot_errno.h" #include "math.h" #define i2c_id 1 #define pca_adrr 0x40 // pca9685设备地址 #define pca_mode1 0x0 #define pca_pre 0xFE #define LED0_ON_L 0x6 #define LED0_ON_H 0x7 #define LED0_OFF_L 0x8 #define LED0_OFF_H 0x9 static OS_Thread_t g_main_thread; void pca_write(uint8_t reg_addr, uint8_t data) { uint8_t buf[1]; buf[0] = data; HAL_I2C_Master_Transmit_Mem_IT(i2c_id, pca_adrr, reg_addr, I2C_MEMADDR_SIZE_8BIT, buf, 1); } uint8_t pca_read(uint8_t reg_addr) { uint8_t buf[1]; HAL_I2C_Master_Receive_Mem_IT(i2c_id, pca_adrr, reg_addr, I2C_MEMADDR_SIZE_8BIT, buf, 1); return buf[0]; } void pca_setfreq(float freq) { uint8_t prescale,old_mode,new_mode; double prescaleval; freq *= 0.92; prescaleval = 25000000; prescaleval /= 4096; prescaleval /= freq; prescaleval -= 1; prescale =(uint8_t)(prescaleval + 0.5f); old_mode = pca_read(pca_mode1); new_mode = (old_mode & 0x7F) | 0x10; pca_write(pca_mode1, new_mode); pca_write(pca_pre, prescale); pca_write(pca_mode1, old_mode); OS_MSleep(2); pca_write(pca_mode1, old_mode | 0xa1); } void pca_setpwm(uint8_t num, uint32_t on, uint32_t off) { pca_write(LED0_ON_L+4*num,on); pca_write(LED0_ON_H+4*num,on>>8); pca_write(LED0_OFF_L+4*num,off); pca_write(LED0_OFF_H+4*num,off>>8); } void pca9685_init(float hz) { pca_write(pca_mode1, 0x0); pca_setfreq(hz); OS_MSleep(500); } void pca_rotate(uint8_t num,uint8_t angle) { uint32_t off=0; off=floor(angle * 2 + angle / 5 + 158); pca_setpwm(num, 0, off); } void i2c_init(unsigned int id){ I2C_InitParam initParam; initParam.addrMode = I2C_ADDR_MODE_7BIT; initParam.clockFreq = 40000; if (HAL_I2C_Init(id, &initParam) != HAL_OK) { printf("i2c init fail!\n"); while(1); } else { printf("i2c init success!\n"); } } static void MainThread(void *arg) { uint8_t i = 0; i2c_init(i2c_id); pca9685_init(60); printf("i2c and pca9685 init done.\n"); while(1){ pca_rotate(0, 0); OS_MSleep(1000); pca_rotate(0, 180); OS_MSleep(1000); } } void PCAMain(void) { printf("PCA9685 Motor Start.\n"); if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL, OS_THREAD_PRIO_APP, 10 * 1024) != OS_OK) { printf("[ERR] Create MainThread Failed\n"); } } SYS_RUN(PCAMain);
狗子的相关步态算法还在调试,使用的舵机是MG90S,走得还不是很流畅,狗腿子会抖,后面需要继续调试,而且供电也是个大问题,不过已经焊了个供电模块稍微解决了,后面还要给狗子加个壳。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
是时候,升级你的 Windows 了「GitHub 热点速览」
不知道多少小伙伴用着 Windows 操作系统,可能会有一个烦恼是有时候操作系统过慢,因为众多拖慢 Windows 系统的组件。Atlas 作为一个修改版的 Windows 系统,能极大提高操作系统运行数据。说到升级,除了 Atlas 之外,还有主打内存安全的 sudo 升级版 sudo-rs,以及 pip 等常见 Python 包管理升级版 rye,还有升级 PG 让它支持向量检索的 pgvector。 当然本周依旧有两个 AI 相关项目,一个用来搞图表,一个用来搞定本地 CPU 推理。 以下内容摘录自微博@HelloGitHub 的 GitHub Trending 及 Hacker News 热帖(简称 HN 热帖),选项标准:新发布 | 实用 | 有趣,根据项目 release 时间分类,发布时间不超过 14 day 的项目会标注 New,无该标志则说明项目 release 超过半月。由于本文篇幅有限,还有部分项目未能在本文展示,望周知 🌝 本文目录 1. 本周特推 1.1 AI 专场 1.2 sudo 和 su 实现:sudo-rs 2. GitHub Trending 周榜...
- 下一篇
一条SQL如何被MySQL架构中的各个组件操作执行的?
摘要:一条SQL如何被MySQL架构中的各个组件操作执行的,执行器做了什么?存储引擎做了什么?表关联查询是怎么在存储引擎和执行器被分步执行的?本文带你探探究竟! 本文分享自华为云社区《一条SQL如何被MySQL架构中的各个组件操作执行的?》,作者:砖业洋__。 1. 单表查询SQL在MySQL架构中的各个组件的执行过程 简单用一张图说明下,MySQL架构有哪些组件,接下来给大家用SQL语句分析 假如SQL语句是这样 SELECT class_no FROM student WHERE name = 'lcy' AND age > 18 GROUP BY class_no 其中name为索引,我们按照时间顺序来分析一下 1.客户端:客户端(如MySQL命令行工具、Navicat、MySQL Workbench或其他应用程序)发送SQL查询到MySQL服务器。 2.连接器:连接器负责与客户端建立连接、管理连接和维护连接。当客户端连接到MySQL服务器时,连接器验证客户端的用户名和密码,然后分配一个线程来处理客户端的请求。 3.查询缓存:查询缓存用于缓存先前执行过的查询及其结果。当收到...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,CentOS7官方镜像安装Oracle11G