Hi3861 OpenHarmony 机械臂 (二)

        前面写了单个舵机的简单控制程序,下面做多个舵机的控制。

        单个舵机控制写完,就将单个舵机堆成一组舵机,先从2台舵机开始。

        将舵机参数生成一个结构体:

// 舵机参数
struct SE_Par
{
    hi_u16 an1;     // 当前角度
    hi_u16 an2;     // 转向角度

    hi_u16 lef;     // 左边界
    hi_u16 mid;     // 中间
    hi_u16 rig;     // 右边界

    hi_u8 pin;      // 端口
    hi_u8 run;      // 运行 0 1
    hi_u8 spa;      // 跨度 0 1 10
    hi_u8 del;      // 延时 0 1
    hi_u8 dir;      // 方向 0 1
};

        然后声明一个舵机参数的数组,这样就得到了一组舵机。将舵机初始化:

struct SE_Par se_ps[SE_PN] = {0};   // 舵机参数
hi_u8 se_pi = 0;                    // 舵机端口

// 舵机参数初始化
hi_void Engine_Init(hi_void)
{
    for(hi_u8 i = 0; i < SE_PN; i++)
    {
        se_ps[i].pin = i;
        se_ps[i].run = 0;
        se_ps[i].spa = 0;
        se_ps[i].dir = 0;
        se_ps[i].del = 0;

        se_ps[i].an1 = 135;
        se_ps[i].an2 = 135;

        se_ps[i].lef = 0;
        se_ps[i].mid = 135;
        se_ps[i].rig = 270;

        PCA9685_Angle(se_ps[i].pin, se_ps[i].an1, 270);
    }

}

        每台舵机初始化完,将舵机转向居中。

        剩下的就是在运行的时候,先通过遥控器设置舵机端口,然后控制相应的舵机的运行。就跟控制单位舵机一样的了。        


// 遥控 控制
hi_u8 RC_Control(hi_u8 con)
{
    hi_u8 ret = 1;

    // 设置跨度

    // 0xa2, 1
    if(con == 0xa2)
    {
        printf(" 1 : \n");
        se_ps[se_pi].spa = 0;
    }

    // 0x62, 2
    if(con == 0x62)
    {
        printf(" 2 : \n");
        se_ps[se_pi].spa = 1;
    }

    // 0xe2, 3
    if(con == 0xe2)
    {
        printf(" 3 : \n");
        se_ps[se_pi].spa = 10;
    }

    // 设置边界

    // 左

    // 0x22, 4
    if(con == 0x22)
    {
        printf(" 4 : \n");
        if(se_ps[se_pi].dir == 0)
        {
            se_ps[se_pi].lef = se_ps[se_pi].an1;
        }

        if(se_ps[se_pi].dir == 1)
        {
            se_ps[se_pi].rig = se_ps[se_pi].an1;
        }
    }

    // 中

    // 0x02, 5
    if(con == 0x02)
    {
        printf(" 5 : \n");
        se_ps[se_pi].mid = se_ps[se_pi].an1;
    }

    // 右

    // 0xc2, 6
    if(con == 0xc2)
    {
        printf(" 6 : \n");
        if(se_ps[se_pi].dir == 0)
        {
            se_ps[se_pi].rig = se_ps[se_pi].an1;
        }

        if(se_ps[se_pi].dir == 1)
        {
            se_ps[se_pi].lef = se_ps[se_pi].an1;
        }
    }

    // 旋转方向设置

    // 0xe0, 7
    if(con == 0xe0)
    {
        printf(" 7 : \n");

        if(se_ps[se_pi].dir == 0)
        {
            se_ps[se_pi].dir = 1;
        }else{
            se_ps[se_pi].dir = 0;
        }
    }

    // 0xa8, 8
    if(con == 0xa8)
    {
        printf(" 8 : \n");
    }

    // 运行延时开关

    // 0x90, 9
    if(con == 0x90)
    {
        printf(" 9 : \n");

        if(se_ps[se_pi].del == 0)
        {
            se_ps[se_pi].del = 1;
        }else{
            se_ps[se_pi].del = 0;
        }
    }

    // 运行到中间

    // 0x98, 0
    if(con == 0x98)
    {
        printf(" 0 : \n");
        se_ps[se_pi].an2 = se_ps[se_pi].mid;
        se_ps[se_pi].run = 1;
    }

    // 退出

    // 0x68, *
    if(con == 0x68)
    {
        printf(" * : \n");
        ret = 0;
    }

    // 重置

    // 0xb0, #
    if(con == 0xb0)
    {
        printf(" # : \n");
        se_ps[se_pi].an1 = 135;
        se_ps[se_pi].an2 = 135;
        se_ps[se_pi].lef = 0;
        se_ps[se_pi].mid = 135;
        se_ps[se_pi].rig = 270;
    }

    // 端口切换

    // 0x18, up
    if(con == 0x18)
    {
        printf(" up : \n");
        if(se_pi < (SE_PN - 1))
        {
            se_pi++;
        }
    }

    // 0x4a, down
    if(con == 0x4a)
    {
        printf(" down : \n");
        if(se_pi > 0)
        {
            se_pi--;
        }
    }

    // 向左运行

    // 0x10, left
    if(con == 0x10)
    {
        printf(" left : \n");
        if(se_ps[se_pi].dir == 0)
        {
            se_ps[se_pi].an2 = Turn_Left(se_ps[se_pi]);
        }
        if(se_ps[se_pi].dir == 1)
        {
            se_ps[se_pi].an2 = Turn_Right(se_ps[se_pi]);
        }
        se_ps[se_pi].run = 1;
    }

    // 向右运行

    // 0x5a, right
    if(con == 0x5a)
    {
        printf(" right : \n");
        if(se_ps[se_pi].dir == 0)
        {
            se_ps[se_pi].an2 = Turn_Right(se_ps[se_pi]);
        }
        if(se_ps[se_pi].dir == 1)
        {
            se_ps[se_pi].an2 = Turn_Left(se_ps[se_pi]);
        }
        se_ps[se_pi].run = 1;
    }

    // 运行停止

    // 0x38, OK
    if(con == 0x38)
    {
        printf(" OK : \n");
        if(se_ps[se_pi].run == 1)
        {
            se_ps[se_pi].run = 0;
            se_ps[se_pi].an2 = se_ps[se_pi].an1;
        }
    }

    // 显示信息
    Display_SE_Data();

    return ret;
}

        但是多台舵机的控制,遇到几个问题:

        第一个是边界问题,舵机组合到一起,工作范围需要设定,否者容易出现砸机的问题,还有就是舵机本身是机械装置,输出的居中位置,在机械齿轮上输出并不一定真的居中,这个时候就要先设置居中位置。

        第二个是方向问题,比如你按遥控的左键,你看到的舵机是右转,舵机的转向方向是固定的,操作习惯认为是反的,这个时候我添加一个方向的参数,可以按右键的时候向左转,就是将舵机的工作模式进行镜像的操作。

        第三个问题是,代码堆到一定程度,就很难维护,一个函数里关联的参数太多,需要修改功能的时候,就连带的改动很大,搞不好就要推倒重写,所以函数的功能独立,将代码解耦到可控的程度。

遥控舵机演示

        遥控器发送指令,控制舵机转到想要的位置,然后将这个位置设定为边界,这样舵机就不会越出工作范围。2台舵机分别控制。

        舵机多了,组合工作靠遥控器就不行了,下一步写网络功能。

             

         

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值