您的位置:首页 > 其它

低端单片机(8bit)的16路舵机调速分析与实现

2015-12-27 17:53 387 查看
低端单片机(8bit)的16路舵机调速分析与实现

By 马冬亮(凝霜 Loki)

一个人的战争(http://blog.csdn.net/MDL13412)

今年的英特尔杯准备做机器人方向,所以在淘宝上买了机器人套件,自己进行组装和编程。机器人装配完如下图所示:



(注:这款机器人由17路舵机组成,其中左右手各2路,左右腿各4路,身体4路,头部1路。)

装配好机器人,首要任务就是让机器人运动起来。看了一下卖家给的控制程序,写的很混乱,维护极差,于是准备自己写一套控制程序,也算是给学弟学妹们留下的一份礼物吧^_^。

首先简单介绍一下我们使用的舵机参数:

*型号.:KCS110M
*速度 :5.0V: 0.14sec/60°
*扭力 :5.0V: 9.5kg/cm
*工作电压:5.0-7.4Volts
*转角范围 : 0~185度

由于是控制机器人,所以我对转角范围的需求是0~180度,那么舵机由0度转到180度需要至少0.6s的时间。

舵机的调速原理其实很简单,通过给定连续的PWM信号,舵机就可以旋转到相应的角度。我们的这款舵机和竞赛的通用舵机基本一致,PWM周期为20ms,复位需要T1=0.5ms的高电平,T2=(20 - 0.5)ms的低电平。每增加1度,需要在T1的基础上加10us。为了让舵机完整的转到对应角度,我们需要至少对舵机连续送0.6s的PWM信号。

由于舵机调速对PWM精度要求很高,传统的12T 8051单片机每个指令周期占12个机器周期,速度不能达到要求。我们选择了STC12C5A60S2这款单片机,这款单片机较传统的12T 8051快至少6倍以上,并配合24MHZ的晶振来控制机器人。

舵机调速一般有两种方法,一种是使用定时器中断进行调速,另外一种是使用软件延时进行调速。

首先分析定时器中断调速的方法:

我的调速精度要求是1度,所以定时器需要定时10us,那么,每200次定时器中断完成一个PWM调速周期。这种编程方式的优点是实现简单,代码容易读懂。其缺点是只能处理少数舵机,不能对大量舵机进行调速。因为每10us发生一次定时中断,而每个机器周期为(1 * 1000 * 1000) / (24 * 1000 * 1000)=0.0417us,则在每个定时器中断中有10 / 0.0417=240个指令周期。我们看下面的程序:

[cpp] view
plaincopyprint?

#include <STC_NEW_8051.H>

void main()

{

volatile int cnt = 0;

volatile int pwm = 0;

volatile int pwmCycle = 10;

cnt = (cnt + 1) % 40;

if (++cnt < pwmCycle)

pwm = 1;

else

pwm = 0;

}

这段程序是模拟定时器中断中对一路舵机进行调速的情况,注意,这里一定要使用volatile关键字,否则程序会由于编译器的优化而错误。对于所有中断中用到的全局变量,我们都需要加上volatile关键字防止编译器优化。下面,我们对这段代码进行反汇编,并计算指令周期数。反汇编代码如下:

[plain] view
plaincopyprint?

C:0x0097 F50C MOV 0x0C,A 3

C:0x0099 750D0A MOV 0x0D,#0x0A 3

C:0x009C E509 MOV A,0x09 2

C:0x009E 2401 ADD A,#0x01 2

C:0x00A0 FF MOV R7,A 2

C:0x00A1 E4 CLR A 1

C:0x00A2 3508 ADDC A,0x08 3

C:0x00A4 FE MOV R6,A 2

C:0x00A5 7C00 MOV R4,#0x00 2

C:0x00A7 7D28 MOV R5,#0x28 2

C:0x00A9 120003 LCALL C?SIDIV(C:0003)

C:0x00AC 8C08 MOV 0x08,R4 3

C:0x00AE 8D09 MOV 0x09,R5 3

C:0x00B0 0509 INC 0x09 4

C:0x00B2 E509 MOV A,0x09 2

C:0x00B4 7002 JNZ C:00B8 3

C:0x00B6 0508 INC 0x08 4

C:0x00B8 AE08 MOV R6,0x08 4

C:0x00BA C3 CLR C 1

C:0x00BB 950D SUBB A,0x0D 3

C:0x00BD E50C MOV A,0x0C 2

C:0x00BF 6480 XRL A,#P0(0x80) 2

C:0x00C1 F8 MOV R0,A 2

C:0x00C2 EE MOV A,R6 1

C:0x00C3 6480 XRL A,#P0(0x80) 2

C:0x00C5 98 SUBB A,R0 2

C:0x00C6 5007 JNC C:00CF 3

C:0x00C8 750A00 MOV 0x0A,#0x00 3

C:0x00CB 750B01 MOV 0x0B,#0x01 3

//C:0x00CE 22 RET

多个if情况时这里应该是一个跳转 3

C:0x00CF E4 CLR A 1

C:0x00D0 F50A MOV 0x0A,A 3

C:0x00D2 F50B MOV 0x0B,A 3

由以上代码可知,一个舵机的调速周期为79+[LCALL C?SIDIV(C:0003) ]条指令周期,所以,对于10us的定时器中断,最多可以调速2路舵机。

接下来我们来分析软件延时的方法进行调速,首先我们需要一个延时函数,那么我们定义一个延时10us的函数如下所示:

[cpp] view
plaincopyprint?

void Delay10us(UINT16 ntimes)

{

for (delayVar1 = 0; delayVar1 < ntimes; ++delayVar1)

for (delayVar2 = 0; delayVar2 < 21; ++delayVar2)

_nop_();

}

如果对每个舵机分别进行调速,那么我们的时间开销为0.6 * 16 = 9.6s,这个时间是不可接受的。由于8位单片机有P0-P3的管脚阵列,那么我们可以利用其中的某一列,同时调速8路舵机,那么我们的时间开销为0.6 * 2 = 1.2s,这个对于我们的机器人来说是完全可以接受的。

同时对8路舵机进行调速的话,我们首先需要对舵机的调速角度进行排序(升序),然后计算出两两舵机舵机的差值,这样就可以同时对8路舵机进行调速了。对于出现的非法角度,我们给这路舵机送全为高电平的PWM信号,使此路舵机保持先前状态。代码如下所示:

[cpp] view
plaincopyprint?

void InitPwmPollint()

{

UCHAR8 i;

UCHAR8 j;

UCHAR8 k;

UINT16 temp;

for (i = 0; i < USED_PIN; ++i)

{

for (j = 0; j < 7; ++j)

{

for (k = j; k < 8; ++k)

{

if (g_diffAngle[i][j] > g_diffAngle[i][k])

{

temp = g_diffAngle[i][j];

g_diffAngle[i][j] = g_diffAngle[i][k];

g_diffAngle[i][k] = temp;

temp = g_diffAngleMask[i][j];

g_diffAngleMask[i][j] = g_diffAngleMask[i][k];

g_diffAngleMask[i][k] = temp;

}

}

}

}

for (i = 0; i < USED_PIN; ++i)

{

for (j = 0; j < 8; ++j)

{

if (INVALID_JOINT_VALUE == g_diffAngle[i][j])

{

g_diffAngle[i][j] = STEERING_ENGINE_FULL_CYCLE;

}

}

}

for (i = 0; i < USED_PIN; ++i)

{

for (j = 7; j >= 1; --j)

{

g_diffAngle[i][j] = g_diffAngle[i][j] - g_diffAngle[i][j - 1];

}

}

}

(注:对于上面用到的一些常量,请大家参考本文最后给出的完整程序。

下面我们举例说明上述代码,假设 g_diffAngle[0][] = {10, 20, 40, 40, 50, 80, 90, 10},那么经过排序后,其变为g_diffAngle[0][] = {10, 10, 20, 40, 40, 50, 80, 90},而g_diffAngleMask[0][]中的值对应个角度使用的管脚的掩码,例如P0.0,则其掩码为0x01,对P0 & 0x01进行掩码计算,就可以对指定的管脚进行操作。我们对角度排序的同时,需要更新管脚的掩码,以达到相互对应的目的。

接下来对角度进行校验,对于不合法的角度,我们使用STEERING_ENGINE_FULL_CYCLE来进行填充,使这路舵机在PWM调速周期内全为高电平。

最后计算差值,计算后g_diffAngle[0][]={10, 0, 10, 20, 0, 10, 30, 10},这样就求出了后面的舵机相对于其前面一路的差值。我们对g_diffAngle[0][0]对应的舵机延时Delay10us(g_diffAngle[0][0])即Delay10us(10),延时完成后我们将这路舵机给低电平,这用到了前面定义的掩码操作。延时完成后,开始延时g_diffAngle[0][1]对应的舵机,Delay10us(g_diffAngle[0][1])即Delay10us(0),然后将此路舵机送低电平。再延时Delay10us(g_diffAngle[0][2])即Delay10us(10),然后再移除,依次类推。这样就能保证在一个PWM周期内对8路舵机同时调速。调速部分代码如下:

[cpp] view
plaincopyprint?

#define PWM_STEERING_ENGINE(group) \

{ \

counter = STEERING_ENGINE_INIT_DELAY; \

for (i = 0; i < 8; ++i) \

counter += g_diffAngle[PIN_GROUP_##group][i]; \

\

for (i = 0; i < 30; ++i) \

{ \

GROUP_##group##_CONTROL_PIN = 0xFF; \

Delay10us(STEERING_ENGINE_INIT_DELAY); \

\

for (j = 0; j < 8; ++j) \

{ \

Delay10us(g_diffAngle[PIN_GROUP_##group][j]); \

GROUP_##group##_CONTROL_PIN &= ~(g_diffAngleMask[PIN_GROUP_##group][j]); \

} \

\

Delay10us(STEERING_ENGINE_CYCLE - counter); \

} \

}

[cpp] view
plaincopyprint?

while (1)

{

PWM_STEERING_ENGINE(1);

}

通过上面的操作,我们便完成了同时对8路舵机的调速操作。

总结:

对于只有1、2路舵机的情况,我们可以使用定时器中断进行调速,其具有实现简单,通俗易懂的有点。而对于多路舵机的情形,就需要使用软件延时进行操作,其优点是可以同时对8路舵机进行调速,效率高,但是其代码不容易实现与调试。

附完整程序:

(注:由于需求变动很大,包括功能和管脚分配等,所以本程序大量使用宏及enum)

[cpp] view
plaincopyprint?

/**

* @file ControlRobot.h

* @author 马冬亮

* @brief 用于对机器人进行控制.

*/

#ifndef CONTROLROBOT_H

#define CONTROLROBOT_H

/**

* @brief 关节角度非法值.

* @ingroup ControlRobot

*

* @details 当关节角度无法确定或捕获关节失败时, 设置为此数值, 机器人接收到此数值则不转动舵机.

*/

#define INVALID_JOINT_VALUE 200

/**

* @brief 定义关节常量用于存取关节角度.

* @ingroup ControlRobot

*/

typedef enum RobotJoint

{

ROBOT_LEFT_SHOULDER_VERTICAL = 0, ///< 左肩膀, 前后转动的舵机

ROBOT_LEFT_SHOULDER_HORIZEN = 1, ///< 左肩膀, 上下转动的舵机

ROBOT_LEFT_ELBOW = 2, ///< 左肘, 左臂肘关节的舵机

ROBOT_RIGHT_SHOULDER_VERTICAL = 3, ///< 右肩膀, 前后转动的舵机

ROBOT_RIGHT_SHOULDER_HORIZEN = 4, ///< 右肩膀, 上下转动的舵机

ROBOT_RIGHT_ELBOW = 5, ///< 右肘, 右臂肘关节的舵机

ROBOT_LEFT_HIP_VERTICAL = 6, ///< 左髋, 左右转动的舵机

ROBOT_LEFT_HIP_HORIZEN = 7, ///< 左髋, 前后转动的舵机

ROBOT_LEFT_KNEE = 8, ///< 左膝盖, 左膝关节的舵机

ROBOT_LEFT_ANKLE = 9, ///< 左踝, 这个舵机不使用

ROBOT_RIGHT_HIP_VERTICAL = 10, ///< 右髋, 左右转动的舵机

ROBOT_RIGHT_HIP_HORIZEN = 11, ///< 右髋, 前后转动的舵机

ROBOT_RIGHT_KNEE = 12, ///< 右膝盖, 右膝关节的舵机

ROBOT_RIGHT_ANKLE = 13, ///< 右踝, 这个舵机不使用

ROBOT_LEFT_FOOT = 14, ///< 左脚, 这个舵机不使用

ROBOT_RIGHT_FOOT = 15, ///< 右脚, 这个舵机不使用

ROBOT_HEAD = 16, ///< 头, 这个舵机不使用

ROBOT_JOINT_AMOUNT = ROBOT_HEAD + 1

} RobotJoint;

typedef enum RobotSteeringEnginePinIndex

{

ROBOT_PIN_INDEX_LEFT_SHOULDER_VERTICAL = 0,

ROBOT_PIN_INDEX_LEFT_SHOULDER_HORIZEN = 1,

ROBOT_PIN_INDEX_LEFT_ELBOW = 2,

ROBOT_PIN_INDEX_RIGHT_SHOULDER_VERTICAL = 3,

ROBOT_PIN_INDEX_RIGHT_SHOULDER_HORIZEN = 4,

ROBOT_PIN_INDEX_RIGHT_ELBOW = 5,

ROBOT_PIN_INDEX_LEFT_HIP_VERTICAL = 6,

ROBOT_PIN_INDEX_RIGHT_HIP_VERTICAL = 7,

ROBOT_PIN_INDEX_LEFT_HIP_HORIZEN = 0,

ROBOT_PIN_INDEX_LEFT_KNEE = 1,

ROBOT_PIN_INDEX_LEFT_ANKLE = 2,

ROBOT_PIN_INDEX_LEFT_FOOT = 3,

ROBOT_PIN_INDEX_RIGHT_HIP_HORIZEN = 4,

ROBOT_PIN_INDEX_RIGHT_KNEE = 5,

ROBOT_PIN_INDEX_RIGHT_ANKLE = 6,

ROBOT_PIN_INDEX_RIGHT_FOOT = 7

} RobotSteeringEnginePinIndex;

typedef enum RobotSteeringEnginePinMask

{

ROBOT_PIN_MASK_LEFT_SHOULDER_VERTICAL = 0x01,

ROBOT_PIN_MASK_LEFT_SHOULDER_HORIZEN = 0x02,

ROBOT_PIN_MASK_LEFT_ELBOW = 0x04,

ROBOT_PIN_MASK_RIGHT_SHOULDER_VERTICAL = 0x08,

ROBOT_PIN_MASK_RIGHT_SHOULDER_HORIZEN = 0x10,

ROBOT_PIN_MASK_RIGHT_ELBOW = 0x20,

ROBOT_PIN_MASK_LEFT_HIP_VERTICAL = 0x40,

ROBOT_PIN_MASK_RIGHT_HIP_VERTICAL = 0x80,

ROBOT_PIN_MASK_LEFT_HIP_HORIZEN = 0x01,

ROBOT_PIN_MASK_LEFT_KNEE = 0x02,

ROBOT_PIN_MASK_LEFT_ANKLE = 0x04,

ROBOT_PIN_MASK_LEFT_FOOT = 0x08,

ROBOT_PIN_MASK_RIGHT_HIP_HORIZEN = 0x10,

ROBOT_PIN_MASK_RIGHT_KNEE = 0x20,

ROBOT_PIN_MASK_RIGHT_ANKLE = 0x40,

ROBOT_PIN_MASK_RIGHT_FOOT = 0x80

} RobotSteeringEnginePinMask;

#define PROTOCOL_HEADER "\xC9\xCA"

#define PROTOCOL_END "\xC9\xCB"

#define PROTOCOL_END_LENGTH 2

#define PROTOCOL_HEADER_LENGTH 2

#define COMMAND_STR_LENGTH (PROTOCOL_HEADER_LENGTH + ROBOT_JOINT_AMOUNT + PROTOCOL_END_LENGTH)

#define COMMAND_STR_BUFFER_SIZE ((COMMAND_STR_LENGTH) + 2)

#endif /* CONTROLROBOT_H */

// main.c

[cpp] view
plaincopyprint?

#include <STC_NEW_8051.H>

#include "ControlRobot.h"

#include<intrins.h>

#define DEBUG_PROTOCOL

typedef unsigned char UCHAR8;

typedef unsigned int UINT16;

#undef TRUE

#undef FALSE

#define TRUE 1

#define FALSE 0

#define MEMORY_MODEL

UINT16 MEMORY_MODEL delayVar1;

UCHAR8 MEMORY_MODEL delayVar2;

#define BAUD_RATE 0xF3

#define USED_PIN 2

#define PIN_GROUP_1 0

#define PIN_GROUP_2 1

#define GROUP_1_CONTROL_PIN P0

#define GROUP_2_CONTROL_PIN P2

#define STEERING_ENGINE_CYCLE 2000

#define STEERING_ENGINE_INIT_DELAY 50

#define STEERING_ENGINE_FULL_CYCLE ((STEERING_ENGINE_CYCLE) - (STEERING_ENGINE_INIT_DELAY))

volatile UCHAR8 MEMORY_MODEL g_angle[2][ROBOT_JOINT_AMOUNT];

volatile bit MEMORY_MODEL g_fillingBufferIndex = 0;

volatile bit MEMORY_MODEL g_readyBufferIndex = 1;

volatile bit MEMORY_MODEL g_swapBuffer = FALSE;

volatile UINT16 MEMORY_MODEL g_diffAngle[USED_PIN][8];

volatile UCHAR8 MEMORY_MODEL g_diffAngleMask[USED_PIN][8] =

{

{

ROBOT_PIN_MASK_LEFT_SHOULDER_VERTICAL,

ROBOT_PIN_MASK_LEFT_SHOULDER_HORIZEN,

ROBOT_PIN_MASK_LEFT_ELBOW,

ROBOT_PIN_MASK_RIGHT_SHOULDER_VERTICAL,

ROBOT_PIN_MASK_RIGHT_SHOULDER_HORIZEN,

ROBOT_PIN_MASK_RIGHT_ELBOW,

ROBOT_PIN_MASK_LEFT_HIP_VERTICAL,

ROBOT_PIN_MASK_RIGHT_HIP_VERTICAL

},

{

ROBOT_PIN_MASK_LEFT_HIP_HORIZEN,

ROBOT_PIN_MASK_LEFT_KNEE,

ROBOT_PIN_MASK_LEFT_ANKLE,

ROBOT_PIN_MASK_LEFT_FOOT,

ROBOT_PIN_MASK_RIGHT_HIP_HORIZEN,

ROBOT_PIN_MASK_RIGHT_KNEE,

ROBOT_PIN_MASK_RIGHT_ANKLE,

ROBOT_PIN_MASK_RIGHT_FOOT

}

};

#ifdef DEBUG_PROTOCOL

sbit P10 = P1 ^ 0; // 正在填充交换区1

sbit P11 = P1 ^ 1; // 正在填充交换区2

sbit P12 = P1 ^ 2; // 交换区变换

sbit P13 = P1 ^ 3; // 协议是否正确

#endif

void Delay10us(UINT16 ntimes)

{

for (delayVar1 = 0; delayVar1 < ntimes; ++delayVar1)

for (delayVar2 = 0; delayVar2 < 21; ++delayVar2)

_nop_();

}

void InitPwmPollint()

{

UCHAR8 i;

UCHAR8 j;

UCHAR8 k;

UINT16 temp;

for (i = 0; i < USED_PIN; ++i)

{

for (j = 0; j < 7; ++j)

{

for (k = j; k < 8; ++k)

{

if (g_diffAngle[i][j] > g_diffAngle[i][k])

{

temp = g_diffAngle[i][j];

g_diffAngle[i][j] = g_diffAngle[i][k];

g_diffAngle[i][k] = temp;

temp = g_diffAngleMask[i][j];

g_diffAngleMask[i][j] = g_diffAngleMask[i][k];

g_diffAngleMask[i][k] = temp;

}

}

}

}

for (i = 0; i < USED_PIN; ++i)

{

for (j = 0; j < 8; ++j)

{

if (INVALID_JOINT_VALUE == g_diffAngle[i][j])

{

g_diffAngle[i][j] = STEERING_ENGINE_FULL_CYCLE;

}

}

}

for (i = 0; i < USED_PIN; ++i)

{

for (j = 7; j >= 1; --j)

{

g_diffAngle[i][j] = g_diffAngle[i][j] - g_diffAngle[i][j - 1];

}

}

}

void InitSerialPort()

{

AUXR = 0x00;

ES = 0;

TMOD = 0x20;

SCON = 0x50;

TH1 = BAUD_RATE;

TL1 = TH1;

PCON = 0x80;

EA = 1;

ES = 1;

TR1 = 1;

}

void OnSerialPort() interrupt 4

{

static UCHAR8 previousChar = 0;

static UCHAR8 currentChar = 0;

static UCHAR8 counter = 0;

if (RI)

{

RI = 0;

currentChar = SBUF;

if (PROTOCOL_HEADER[0] == currentChar) // 协议标志

{

previousChar = currentChar;

}

else

{

if (PROTOCOL_HEADER[0] == previousChar && PROTOCOL_HEADER[1] == currentChar) // 协议开始

{

counter = 0;

previousChar = currentChar;

g_swapBuffer = FALSE;

}

else if (PROTOCOL_END[0] == previousChar && PROTOCOL_END[1] == currentChar) // 协议结束

{

previousChar = currentChar;

if (ROBOT_JOINT_AMOUNT == counter) // 协议接受正确

{

if (0 == g_fillingBufferIndex)

{

g_readyBufferIndex = 0;

g_fillingBufferIndex = 1;

}

else

{

g_readyBufferIndex = 1;

g_fillingBufferIndex = 0;

}

g_swapBuffer = TRUE;

#ifdef DEBUG_PROTOCOL

P13 = 0;

#endif

}

else

{

g_swapBuffer = FALSE;

#ifdef DEBUG_PROTOCOL

P13 = 1;

#endif

}

counter = 0;

}

else // 接受协议正文

{

g_swapBuffer = FALSE;

previousChar = currentChar;

if (counter < ROBOT_JOINT_AMOUNT)

g_angle[g_fillingBufferIndex][counter] = currentChar;

++counter;

}

} // if (PROTOCOL_HEADER[0] == currentChar)

SBUF = currentChar;

while (!TI)

;

TI = 0;

} // (RI)

}

void FillDiffAngle()

{

// 设置舵机要调整的角度

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_LEFT_SHOULDER_VERTICAL];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_LEFT_SHOULDER_HORIZEN];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_ELBOW] = g_angle[g_readyBufferIndex][ROBOT_LEFT_ELBOW];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_SHOULDER_VERTICAL];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_SHOULDER_HORIZEN];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_ELBOW] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_ELBOW];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_HIP_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_LEFT_HIP_VERTICAL];

g_diffAngle[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_HIP_VERTICAL] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_HIP_VERTICAL];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_HIP_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_LEFT_HIP_HORIZEN];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_KNEE] = g_angle[g_readyBufferIndex][ROBOT_LEFT_KNEE];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_ANKLE] = g_angle[g_readyBufferIndex][ROBOT_LEFT_ANKLE];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_FOOT] = g_angle[g_readyBufferIndex][ROBOT_LEFT_FOOT];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_HIP_HORIZEN] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_HIP_HORIZEN];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_KNEE] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_KNEE];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_ANKLE] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_ANKLE];

g_diffAngle[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_FOOT] = g_angle[g_readyBufferIndex][ROBOT_RIGHT_FOOT];

// 复位舵机管脚索引

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_VERTICAL] = ROBOT_PIN_MASK_LEFT_SHOULDER_VERTICAL;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_SHOULDER_HORIZEN] = ROBOT_PIN_MASK_LEFT_SHOULDER_HORIZEN;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_ELBOW] = ROBOT_PIN_MASK_LEFT_ELBOW;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_VERTICAL] = ROBOT_PIN_MASK_RIGHT_SHOULDER_VERTICAL;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_SHOULDER_HORIZEN] = ROBOT_PIN_MASK_RIGHT_SHOULDER_HORIZEN;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_ELBOW] = ROBOT_PIN_MASK_RIGHT_ELBOW;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_LEFT_HIP_VERTICAL] = ROBOT_PIN_MASK_LEFT_HIP_VERTICAL;

g_diffAngleMask[PIN_GROUP_1][ROBOT_PIN_INDEX_RIGHT_HIP_VERTICAL] = ROBOT_PIN_MASK_RIGHT_HIP_VERTICAL;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_HIP_HORIZEN] = ROBOT_PIN_MASK_LEFT_HIP_HORIZEN;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_KNEE] = ROBOT_PIN_MASK_LEFT_KNEE;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_ANKLE] = ROBOT_PIN_MASK_LEFT_ANKLE;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_LEFT_FOOT] = ROBOT_PIN_MASK_LEFT_FOOT;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_HIP_HORIZEN] = ROBOT_PIN_MASK_RIGHT_HIP_HORIZEN;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_KNEE] = ROBOT_PIN_MASK_RIGHT_KNEE;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_ANKLE] = ROBOT_PIN_MASK_RIGHT_ANKLE;

g_diffAngleMask[PIN_GROUP_2][ROBOT_PIN_INDEX_RIGHT_FOOT] = ROBOT_PIN_MASK_RIGHT_FOOT;

}

#define PWM_STEERING_ENGINE(group) \

{ \

counter = STEERING_ENGINE_INIT_DELAY; \

for (i = 0; i < 8; ++i) \

counter += g_diffAngle[PIN_GROUP_##group][i]; \

\

for (i = 0; i < 30; ++i) \

{ \

GROUP_##group##_CONTROL_PIN = 0xFF; \

Delay10us(STEERING_ENGINE_INIT_DELAY); \

\

for (j = 0; j < 8; ++j) \

{ \

Delay10us(g_diffAngle[PIN_GROUP_##group][j]); \

GROUP_##group##_CONTROL_PIN &= ~(g_diffAngleMask[PIN_GROUP_##group][j]); \

} \

\

Delay10us(STEERING_ENGINE_CYCLE - counter); \

} \

}

void main()

{

UCHAR8 i;

UCHAR8 j;

UINT16 counter;

InitSerialPort();

P1 = 0xFF;

// 初始化舵机角度

for (i = 0; i < ROBOT_JOINT_AMOUNT; ++i)

{

g_angle[0][i] = 45;

g_angle[1][i] = 45;

}

for (i = 0; i < USED_PIN; ++i)

for (j = 0; j < 8; ++j)

g_diffAngle[i][j] = 0;

FillDiffAngle();

InitPwmPollint();

while (1)

{

#ifdef DEBUG_PROTOCOL

if (g_fillingBufferIndex)

{

P11 = 0;

P10 = 1;

}

else

{

P11 = 1;

P10 = 0;

}

if (g_swapBuffer)

P12 = 0;

else

P12 = 1;

#endif

if (g_swapBuffer)

{

FillDiffAngle();

g_swapBuffer = FALSE;

InitPwmPollint();

}

PWM_STEERING_ENGINE(1)

PWM_STEERING_ENGINE(2)

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: