bobo 发表于 2015-3-7 18:00:34

HCR机器人实验1-建立底层传感器平台

    HCR (Home Care Robot)开源家用机器人平台在各位爱好者和工程师的协助之下迎来了全新一代V2。它一如既往的集成了功能强大、扩展丰富的机械平台。HCR移动机器人套件是一套两轮驱动的三层机器人平台,当然你也可以根据需求调整所使用的部件。套装包含有两个电机,两只轮胎,一只万向轮,以及相关金属板及配套硬件。支撑结构包括伺服机和传感器,此结构上含有专用于mini-itx主板的接口。
新HCR平台能够赋予用户全新的体验,用户能够自由发挥创想力,例如在平台上结合Kinect之类的部件。

最近拿到HCR V2版本准备组建一个自己的家用机器人。选择的部件如下:
1、HCR家用机器人开源项目平台                     1只   平台包括全部的机械结构及其电机,本身还带了3个碰撞开关
2、Veyron 威龙 双路12A直流有刷电机驱动器   1只   带PID自整定的闭环电机控制及其驱动器,用了这个驱动器,电机方面的控制就不需要写程序了
3、11.1V/12AH大电流锂聚合电池                  1只   足够机器人运行半天到一天的
4、DC-DC升降压电源模块                               1只   通过这个模块升降压到 12V提供给 Bluno Mega1280控制器及其PC供电,模块不管电池电压超过12V或者低于12V都可以稳压
5、GP2Y0A21 距离传感器                              8只   负责低矮物体的检测,探测距离:10-80cm
6、数字防跌落传感器                                    4只   楼梯等的跌落检测
7、URM04 V2.0超声波测距模块                     6只   检测更远距离的障碍物,使用RS485总线连接使用比较方便,探测距离:4-500cm
8、USB/RS232/RS485/TTL 协议转换器            1只   使用这个模块将主板TTL电平串口转换为RS485接口 连接URM04超声波传感器
9、Bluno Mega1280控制器                              1只   内带蓝牙无线下载和通信功能的Arduoino Mega主板,通过无线方式 脱离了USB电缆的束缚。下载程序和通信都比较方便
10、MEGA传感器扩展板 V2.4                        1只   扩展板将Bluno Mega1280控制器的接口全部引出为3PIN的排针,这样传感器就可以直接插上去
11、USB BLE-LINK V1.0 Bluno无线下载适配器 1只   插在电脑主机上,建立和Bluno Mega1280控制器的无线连接,完成下载程序和无线通信
12、DC2.1电源转接头 公头                              1只   用于将12V电源线连接到 Bluno Mega1280控制器

装配好底层结构后对电池和电机驱动器进行安装


我们可以使用USB/RS232/RS485/TTL 协议转换器 连接电脑和Veyron 威龙 双路12A直流有刷电机驱动器 进行初步的设置。
对 HCR使用了一款 12V 直流减速电机146rpm 带编码器。他的减速比是51:1,编码器线数是 13.

设置教程参考 Veyron 电机驱动器快速上手
然后对加减速进行设置:
发送: 1,SAD,1,100,1000回车换行
         1,SAD,2,100,1000回车换行
发送:1,EEPSAV回车换行
保存设置的值 (注意一定要保存,否则断电或者重启就没有了)
两条命令将减速度调高,这样可以使小车尽快的刹车。

发送命令:1,RCONFIG回车换行
设置后的参数如下,可看到当前16V电池的情况下电机转速可以到 164r/min,我们可以发送0-164r/min这样的控制指令(电池后来我使用了4S电池)。
/*Common Parameters*/
ID                         : 1
BaudRate                   : 57600bps
Voltage Range            : 6.0-36.0V
Maximum Continuous Current : 12000mA
Maximum Peaky Current      : 20000mA
Protected Temperature      : 100C
Signal Mode                : Discontinuous
PPM Signal Range         : 500-2500us
PWM Type                   : Hpwm-Lpwm(on-off-on)
Direction Type             : CW/CCW
Discontinuous Timeout      : 1000ms
Start Detection Mode       : Non Zero Detection

/*Parameters Of Motor1*/
Reduction Gear Ratio       : 51.00
Encoder Resolution         : 13
Maximum Velocity         : 168r/min
Velocity Mode            : Loop
Acceleration               : 100r/min/s
Deceleration               : 1000r/min/s
PID_Kp                     : 0.330
PID_Ti                     : 16
PID_Td                     : 4

/*Parameters Of Motor2*/
Reduction Gear Ratio       : 51.00
Encoder Resolution         : 13
Maximum Velocity         : 164r/min
Velocity Mode            : Loop
Acceleration               : 100r/min/s
Deceleration               : 1000r/min/s
PID_Kp                     : 0.338
PID_Ti                     : 16
PID_Td                     : 4
因为是机器人项目,这里将控制方式设置为间断模式,见Veyron 电机驱动器快速上手

测试速度控制,需要注意的是,间断控制方式,如果没有发送指令,驱动器会停止工作并报错,后面并不会在执行控制命令,所以保险起见每次发送的控制指令可以在上面追加
下面对电机进行速度控制:
例如将M1的同步转速设定为100r/min
*发送:
1,CER回车换行
1,SVS,1,100回车换行

电机1反方向 100转每秒
1,CER回车换行
1,SVS,1,-100回车换行

电机2正方向 100转每秒
1,CER回车换行
1,SVS,2,100回车换行

电机2反方向 100转每秒
1,CER回车换行
1,SVS,2,-100回车换行

读取电机1编码器计数值用于确定机器人运行轨迹
1,GEP,1回车换行
返回值
如果电机是正方向旋转那么这个值是正数累加。

如果电机是反方向旋转这个值将计数值累减,减到0后,出现负

清除编码器计数值
1,CEP,1回车换行

装配HCR第二层结构安装控制板和超声波,并对超声波进行设置








首先使用 USB/RS232/RS485/TTL 协议转换器 逐个对6个URM04超声波进行设置,波特率19200BPS此时RS485总线只能接一个超声波,便于设置地址。


按照HCR为主体超声波的编址为:


前左    前中前右
0x11   0x120x13
   
      HCR


后左   后中   后右
0x14   0x150x16


下面是对超声波设置地址及其测试的命令,16进制发送
55 aa ab 01 55 11 11    返回 55 AA 10 01 55 01 66    设置为地址0X11
55 aa 11 00 01 11      返回 无    触发产生一次地址为0X11的模块测距
55 aa 11 00 02 12      返回 55 AA 10 02 02 00 16 29 读取地址为0X11模块测量距离
55 aa 11 00 03 13      返回 55 AA 10 02 03 00 F2 06 读取地址为0X11模块的温度

55 aa ab 01 55 12 12    地址0X12
55 aa 12 00 01 12
55 aa 12 00 02 13

55 aa ab 01 55 13 13    地址0X13
55 aa 13 00 01 13   
55 aa 13 00 02 14

55 aa ab 01 55 14 14    地址0X14
55 aa 14 00 01 14      
55 aa 14 00 02 15


55 aa ab 01 55 15 15    地址0X15
55 aa 15 00 01 15      
55 aa 15 00 02 16

55 aa ab 01 55 16 16    地址0X16
55 aa 16 00 01 16      
55 aa 16 00 02 17

设置完毕后将6个超声波级联,通过USB/RS232/RS485/TTL 协议转换器将RS485转换为TTL连接到 Bluno Mega1280控制器 的Serial2串口
Veyron 威龙 双路12A直流有刷电机驱动器 连接到Bluno Mega1280控制器 的Serial3串口
下面是安装完毕HCR底层


例子代码
例子代码使用了Arduino操作系统 -ProtoThreads这样可以专注设计各个进程,减小了各个程序之间的影响。
关于传感器的连接可以参考对端口的定义,代码实现了底层传感器的读取、电机驱动器的控制及其跌落、碰撞传感器的刹车机制。
所有传感器的数据都保存在变量里面,方便上层PC对数据的读取。后面要做的工作是编写 适合ROS的通信协议将数据传输到ROS。通过ROS仿真模型来实施显示数据。
#include <pt.h>    //ProtoThreads必须包含的头文件
#include <TimerOne.h> //使用定时器0来做时间片的定时

//---------------------跌落和碰撞传感器定义---------------------------------------------------
#define dropIsrFL2//D2跌落传感器前左,机器人离地距离大于厘米输出高电平
#define dropIsrFR3//D3跌落传感器前右,机器人离地距离大于厘米输出高电平
#define dropIsrBL4//D4跌落传感器后左,机器人离地距离大于厘米输出高电平
#define dropIsrBR5//D5跌落传感器后右,机器人离地距离大于厘米输出高电平
#define crashIsrFL 6//D6碰撞传感器左,机器人碰撞输出地电平
#define crashIsrFM 7//前中间碰撞传感器 接7口
#define crashIsrFR 8//D8碰撞传感器右,机器人碰撞输出地电平

//---------------------红外传感器定义---------------------------------------------------------
#define infraredDistanceF1A6//HCR机器人 前端从左到右第1只GP2YOA21红外测距传感器
#define infraredDistanceF2A7//第2只GP2YOA21红外测距传感器
#define infraredDistanceF3A8
#define infraredDistanceF4A9
#define infraredDistanceF5A10
#define infraredDistanceB1A11 //HCR机器人后端从左到右第1只GP2YOA21红外测距传感器
#define infraredDistanceB2A12
#define infraredDistanceB3A13



static int timer50msCounter1; //timer50msCounter为定时计数器
static int timer50msCounter2;
static int timer50msCounter3;
static int timer50msCounter4;
static int timer50msCounter5;
static int state1=0;          //state为灯的状态
boolean abortStatus = false;

#define dropFlgeFL0b00000001//跌落传感器前左 状态字 1 : 传感器动作
#define dropFlgeFR0b00000010//跌落传感器前右 状态字 1: 传感器动作
#define dropFlgeBL0b00000100//跌落传感器后左 状态字 1: 传感器动作
#define dropFlgeBR0b00001000//跌落传感器后右 状态字 1: 传感器动作
#define crashFlgeFL 0b00010000//碰撞传感器左 状态字 1: 传感器动作
#define crashFlgeFM 0b00100000//碰撞传感器中 状态字 1: 传感器动作
#define crashFlgeFR 0b01000000//碰撞传感器右 状态字 1: 传感器动作
byte crashDropSensorStatus = 0;//定义碰撞和跌落传感器状态字,每bit代表一个传感器状态 1代表触发

byte infraredRange;//8个红外传感器测距结果,单位 厘米
int batteryVoltage;   //电源电压 123代表 12.3V
long EncoderCount1 = 0;//编码器计数范围为:-2147483648~2147483647
long EncoderCount2 = 0;
unsigned int ultrasonicDistance;//6个超声波测量距离值,1-500厘米

int M1Speed = 0;//电机1速度-164 到 164, -164反转最大速度, 0 电机停止,164正转最大速度
int M2Speed = 0;//电机2速度-164 到 164

#define VOLTAGE_OUT1 //电压输出
#define ENCODER_OUT1 //编码器信息
#define IR_OUT      //红外传感器数据输出
#define U_OUT1   //超声波输出使能

static struct pt pt1, pt2,pt3,pt4,pt5;

/*--------------------------------------------------------------------------------------------
函数说明:底层跌落,碰撞,红外,超声波传感器读取
参数说明:无
返回值:无
---------------------------------------------------------------------------------------------*/
void readSensor(void)
{
byte i = 0;
int val = 0;

if(digitalRead(dropIsrFL) == HIGH)
{
   abortHandle();//机器人异常处理程序
   crashDropSensorStatus |= dropFlgeFL;
   }
if(digitalRead(dropIsrFR) == HIGH)
{
   abortHandle();//机器人异常处理程序   
   crashDropSensorStatus |= dropFlgeFR;
   }
if(digitalRead(dropIsrBL) == HIGH)
{
    abortHandle();//机器人异常处理程序
   crashDropSensorStatus |= dropFlgeBL;
   }
if(digitalRead(dropIsrBR) == HIGH)
{
    abortHandle();//机器人异常处理程序
   crashDropSensorStatus |= dropFlgeBR;
   }
if(digitalRead(crashIsrFL) == LOW)
{
   abortHandle();//机器人异常处理程序
   crashDropSensorStatus |= crashFlgeFL;
   }
if(digitalRead(crashIsrFM) == LOW)
{
   abortHandle();//机器人异常处理程序
   crashDropSensorStatus |= crashFlgeFM;
}
if(digitalRead(crashIsrFR) == LOW)
{
   abortHandle();//机器人异常处理程序
   crashDropSensorStatus |= crashFlgeFR;
}
for(i = 0;i < 8;i++)
{
    val = analogRead(i+6);
    val = (6762/(val-9))-4;
    infraredRange = (byte)val;
}
   #ifdefIR_OUT   //输出 红外传感器信息
      Serial.print("IR Sensor out:");
    for(i=0;i<8;i++)
    {         
      Serial.print(infraredRange,DEC);
      Serial.print("");
    }
    Serial.println(" ");
#endif
   
motorGetSystemVoltage(&batteryVoltage);//获取系统电压

#ifdefVOLTAGE_OUT   //输出 电压值
      Serial.print("Battery Voltage:");
      Serial.println(batteryVoltage,DEC);
#endif

motorGetEncoder(&EncoderCount1,&EncoderCount2);//获取编码器累计脉冲数

#ifdefENCODER_OUT   //输出 电压值
      Serial.print("Encoder:");
      Serial.print(EncoderCount1,DEC);
      Serial.print("");
      Serial.println(EncoderCount2,DEC);
      Serial.println("");
#endif   

}

/*--------------------------------------------------------------------------------------------
函数说明:跌落\碰撞\红外传感器读取线程,每50ms读取一次
参数说明:*pt - ProtoThreads 操作系统指针
返回值:无
---------------------------------------------------------------------------------------------*/
static int ReadSensorThread(struct pt *pt)
{
PT_BEGIN(pt);//线程开始
while(1) //每个线程都不会死
{
    PT_WAIT_UNTIL(pt, timer50msCounter1>0); //如果时间满了50毫秒,则继续执行,否则记录运行点,退出线程1
    readSensor();//读取一次传感器
    timer50msCounter1 = 0; //计数器置零
}
PT_END(pt); //线程结束
}

/*--------------------------------------------------------------------------------------------
函数说明:电机控制线程,每500ms发送一次电机控制命令
参数说明:*pt - ProtoThreads 操作系统指针
返回值:无
---------------------------------------------------------------------------------------------*/
static int MotoControlThread(struct pt *pt)
{
PT_BEGIN(pt);//线程开始
while(1) //每个线程都不会死
{
    PT_WAIT_UNTIL(pt, timer50msCounter2 >= 10); //如果时间满了500毫秒,则继续执行,否则记录运行点,退出线程1
   // 测试是否有报警信号,确认是否使能驱动
    Serial3.println("1,CER");   
    motorControl(M1Speed,M2Speed);
    timer50msCounter2 = 0; //计数器置零
}
PT_END(pt); //线程结束
}

/*--------------------------------------------------------------------------------------------
函数说明:线程2,控制灯1
参数说明:*pt - ProtoThreads 操作系统指针
返回值:无
---------------------------------------------------------------------------------------------*/
static int LEDBlinkThread(struct pt *pt)
{
PT_BEGIN(pt); //线程开始
while(1)
{    //每个线程都不会死
    PT_WAIT_UNTIL(pt, timer50msCounter3 >= 10); //如果时间满了500毫秒,则继续执行,否则记录运行点,退出线程2
    timer50msCounter3 = 0;//计数清零
    digitalWrite(13,state1);
    state1=!state1; //灯状态反转
}
PT_END(pt);//线程结束
}

/*--------------------------------------------------------------------------------------------
函数说明:电机测试进程
参数说明:*pt - ProtoThreads 操作系统指针
返回值:无
---------------------------------------------------------------------------------------------*/
static int MotoTestThread(struct pt *pt)
{
static int i;
PT_BEGIN(pt); //线程开始
while(1)
{
    for(i=0;i<164;i++)
    {
      if(abortStatus == true)
      {
      timer50msCounter4 = 0;//计数清零delay
      PT_WAIT_UNTIL(pt, timer50msCounter4 >= 40); //如果时间满了2000毫秒,则继续执行,否则记录运行点,退出线程
      abortStatus = false;
      }
      M1Speed = i;//设置左右两个电机的速度
      M2Speed = i;
      motorControl(M1Speed,M2Speed);
      timer50msCounter4 = 0;//计数清零
      PT_WAIT_UNTIL(pt, timer50msCounter4 >= 1); //如果时间满了50毫秒,则继续执行,否则记录运行点,退出线程
    }
    for(i=0;i>-164;i--)
    {
      if(abortStatus == true)
      {
      timer50msCounter4 = 0;//计数清零
      PT_WAIT_UNTIL(pt, timer50msCounter4 >= 40); //如果时间满了2000毫秒,则继续执行,否则记录运行点,退出线程
      abortStatus = false;
      }
      M1Speed = i;//设置左右两个电机的速度
      M2Speed = i;
      motorControl(M1Speed,M2Speed);
      timer50msCounter4 = 0;//计数清零
      PT_WAIT_UNTIL(pt, timer50msCounter4 >= 1); //如果时间满了50毫秒,则继续执行,否则记录运行点,退出线程
    }
}
PT_END(pt);//线程结束
}

/*--------------------------------------------------------------------------------------------
函数说明:超声波读取进程,刷新频率5HZ
参数说明:*pt - ProtoThreads 操作系统指针
返回值:无
---------------------------------------------------------------------------------------------*/
static int UltrasonicReadThread(struct pt *pt)
{
static byte i;
static byte temp1;
static unsigned int distance;
PT_BEGIN(pt); //线程开始
while(1)
{   
    for(i=0;i<3;i++)
    {
      UltrasonicTriggerCommand(0x11+i);//触发URM04超声波及其和他相背对方向的另外一个超声波
      UltrasonicTriggerCommand(0x16-i);
      timer50msCounter5 = 0;//计数清零
      PT_WAIT_UNTIL(pt, timer50msCounter5 >= 1); //如果时间满了50毫秒,则继续执行,否则记录运行点,退出线程
    }
    for(i=0;i<6;i++)
    {
      if(UltrasonicReadCommand(0x11+i,&distance))
      {
      ultrasonicDistance = distance;      
      }
      else ultrasonicDistance = 0xffff;
    }
    #ifdefU_OUT
    Serial.print("Ultrasonic:");
    for(i=0;i<6;i++)
    {         
      Serial.print(ultrasonicDistance,DEC);
      Serial.print("");
    }
    Serial.println(" ");
    #endif
}   

PT_END(pt);//线程结束
}

/*--------------------------------------------------------------------------------------------
函数说明:初始化函数
参数说明:无
返回值:无
---------------------------------------------------------------------------------------------*/
void setup()
{
Serial.begin(57600);    //COM用于debug
Serial2.begin(19200);//COM2用于读取URM04超声波
Serial3.begin(57600);//COM3用于Veyron电机驱动控制
pinMode(13,OUTPUT);
pinMode(dropIsrFL,INPUT);//D2跌落传感器前左,机器人离地距离大于厘米输出高电平
pinMode(dropIsrFR,INPUT);//D3跌落传感器前右,机器人离地距离大于厘米输出高电平
pinMode(dropIsrBL,INPUT);//D21跌落传感器后左,机器人离地距离大于厘米输出高电平
pinMode(dropIsrBR,INPUT);//D20跌落传感器后右,机器人离地距离大于厘米输出高电平
pinMode(crashIsrFL,INPUT);//D19碰撞传感器左,机器人碰撞输出地电平
pinMode(crashIsrFM,INPUT);//D17碰撞传感器前中,机器人碰撞输出地电平
pinMode(crashIsrFR,INPUT);//D18碰撞传感器右,机器人碰撞输出地电平   

Timer1.initialize(50000); //设置定时器每50000微秒,也就是50毫秒钟进入一次中断服务程序
Timer1.attachInterrupt( timer1Isr ); //定义中断后的服务程序
PT_INIT(&pt1);//线程1初始化
PT_INIT(&pt2);//线程2初始化
PT_INIT(&pt3);//线程3初始化
PT_INIT(&pt4);//线程4初始化
PT_INIT(&pt5);//线程5初始化   
motorCleanEncoder(1);
motorCleanEncoder(2);
}

/*--------------------------------------------------------------------------------------------
函数说明:主函数循环
参数说明:无
返回值:无
---------------------------------------------------------------------------------------------*/
void loop () //这就是进行线程调度的地方
{
ReadSensorThread(&pt1);//执行线程1
MotoControlThread(&pt2);//执行线程2
LEDBlinkThread(&pt3);//执行线程3
MotoTestThread(&pt4);//执行线程4
UltrasonicReadThread(&pt5);//执行线程5
}

/*--------------------------------------------------------------------------------------------
函数说明:机器人异常处理程序
参数说明:无
返回值:无
---------------------------------------------------------------------------------------------*/
void abortHandle()
{
M1Speed = 0;//将左右两个电机的速度降低到0
M2Speed = 0;
motorControl(M1Speed,M2Speed);
abortStatus = true;
}超声波数据可以反馈了
下一个实验:《HCR机器人实验2-ROS系统和HCR Arduino控制板通信》





hnyzcj 发表于 2015-3-8 11:15:21

这个平台貌似非常强大哦。

Youyou 发表于 2015-3-8 20:44:33

厉害,注释清晰,学习下!

Jaky_wang 发表于 2015-4-8 19:48:37

TimerOne.h这个没有怎么办?

bobo 发表于 2015-4-12 15:43:12

Jaky_wang 发表于 2015-4-8 19:48
TimerOne.h这个没有怎么办?
这个帖子的附件里面有,
https://mc.dfrobot.com.cn/thread-11027-1-1.html

hnyzcj 发表于 2015-11-7 20:15:14

LZ太厉害

凌风清羽 发表于 2016-6-30 21:07:01

为毛HCR裸机就要2200大洋啊,是哪里值钱啊
页: [1]
查看完整版本: HCR机器人实验1-建立底层传感器平台