ARDUINO多功能灾难现成搜救机器人
针对矿难、地震等灾难现场的搜救专用机器人,具有越障能力强、功能多、体积小、能耗低等特点,可快速锁定被困人员所处区域,及时掌握被困人员的生存状态以及现场环境状况(预计二期可加入GPS,摄像头模块实现灾难现场画面传输与被困人员定位功能)采用国内领先的ONENET云平台解决方案,在小循环和大循环中均可以将数据提供到云端进行采集分析,以供后期数据处理。搜救只是该小车多功能中一个具体展示,它更多是作为一个平台实行开源即DIT(DO IT TOGETHER)策略让它的功能不止于此。模块化的设计,让创客创意自由发挥。
机器人由“行走部分”“控制部分”以及“通讯部分”组成。
机器人采用ARDUINO小车平台作为行走机构,,整体结构的蝙蝠仿生设计使机器人能够自主稳定适应复杂地形,多传感器的设计可使机器人对外界环境有初步的自主判断。
机器人具备“环境探测”“人员搜索”“辅助救援”(二期补充)功能。
温度、湿度等传感器可实时监测灾难现场环境。180°超声波云台,有效地扩大工作范围,可快速精确实现路径规划功能。
机器人采用安可信ESP8266,2.4G频率无线数据通讯,抗干扰能力强,信息通讯质量好。同时人机界面的设计方便操作人员及时掌握灾难现场信息,减少操作人员的疲劳程度。 该机器人同时也是个搭载平台,借助于机器人优越的驱动及越障性能,可以为机器人搭载一定体积的其它救援设备。针对不同应用场合,对机器人功能进行模块化调整,从而实现一个移动平台多种应用场合的用途。
现有的搜救机器人多为轮式、履带式以及蛇形式。履带式能够提供较大牵引力,但能耗较高,适应复杂地形能力有限;蛇形式在某些特殊场合机动性能优越,但运动平稳性差,承载能力弱,结构和控制都较复杂。
该作品车体的仿生设计使机器人具备较强的越障能力,强磁碳刷减速电机的驱动设计进一步提高机器人越障能力。 在人员搜索方面,传统的搜索类机器人仅依靠摄像头进行人员搜索,操作人员容易疲劳。该机器人采用人体红外热释电传感器配以自主移动轮式平台,有效地扩大传感器工作范围,可快速精确搜索到被困人员。
机器人通过路劲规划算法自行移动,通过人机界面观测机器人的运动状态,同时机器人将现场各种反馈信息实时传递回界面供操作人员参考。
技术特点及优势:成熟的ARDUINO解决方案使机器人具备良好的移动性能及越障能力;180°云台舵机为其提供了开阔的工作范围;使用2.4G无线频率进行数据传输,有效地提高了抗干扰能力,保证信息质量。
适应范围及推广前景效益预测:该机器人可应用于矿难、地震等突发灾难现场进行环境探测、人员搜索、辅助救援。该机器人同时也是个移动平台,针对不同应用场合,对功能进行模块化调整,从而实现一个移动平台多种应用场合的用途。生命无价,搜救人员以及被困人员的人身安全同等重要。及时掌握灾难现场环境状况可以有效保障搜救人员的人生安全,成功搜索到被困人员并给予营养补给,可以有效延续被困人员生命,为其提供生存信心。
国内外,天灾人祸频繁发生,急需能够用于灾难现场的专用搜救装备。国外,以Irobot公司的Packbot以及“路测”机器人为例,两者均为履带式机器人,不是专为矿难场合设计,因此其适应轨道、狭窄空间以及复杂地形能力非常有限,尤其是“路测”机器人体积庞大,不适合针对矿难情况进行营救。2010年11月22日,“路测”机器人在新西兰派克河煤矿爆炸事故中仅行进550米就失去了工作能力。
Packbot机器人虽然体积小巧,但其功能十分单一,控制也较为复杂。而且履带式机器人能耗较高,不利于矿难救援。国内以沈阳新松机器人自动化有限公司和山东省科学院自动化研究所的井下探测救援机器人为例,这是国内首款专门针对井下救援设计的机器人,在功能上也相对全面,但其底盘较低,移动平台适应复杂地形能力一般。 针对矿井内轨道、狭窄空间等地形较为复杂,传统的轮式机器人越障能力差,腿式机器人控制复杂,蠕动式针对特定场合适应能力强,但其承载能力差的特点,该类机器人均不能较好适应矿井内复杂地形。借鉴Rhex与Whegs单轮腿与三轮腿结构,
我们采用成熟的ARDUINO小车平台方案,适应经过测试,其适应复杂地形能力强,而且机器人体积小巧,整体机械效率高,能耗较低,该机器人针对矿难现场可能出现的恶劣环境配备温度、红外、超声波和180°云台舵机可以在灾难发生后的最短时间内被投入现场,并迅速接近目标,搜集温度、湿度等信息,确定被困人员位置,并进行一些辅助救援工作。IOT的运用契合智能硬件发展契机,前景良好。
stm32103rct6主函数
#include "stm32f10x.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "usart1.h"
#include "usart2.h"
#include "utils.h"
#include "sht20.h"
#include "hal_i2c.h"
#include "esp8266.h"
#define API_KEY "y9cnjKRERNRccpf06Ndi=RYR0Iw=" //需要定义为用户自己的参数
#define DEV_ID "3226414" //需要定义为用户自己的参数
/**
* @brief 利用I2C接口,采集温湿度传感器的值,使用HTTP协议上传到OneNET
* @attention 使用UART2连接ESP8266模块,使用透传模式发送和接收数据
* 使用UART1作为调试打印串口,使用printf将从该接口打印消息
*
*/
uint32_t HTTP_PostPkt(char *pkt, char *key, char *devid, char *dsid, char *val);
int main(void)
{
uint16_t temp, humi; //温湿度
char HTTP_Buf[400]; //HTTP报文缓存区
char tempStr[5]; //字符串格式温度
char humiStr[5]; //字符串格式湿度
int len;
USART1_Config(); //USART1作为调试串口
USART2_Config(); //USART2用于连接ESP8266模块
Hal_I2C_Init(); //I2C初始化,用于连接温湿度传感器
ESP8266_Init(); //ESP8266初始化
printf("ESP8266 init over\r\n");
//SHT20_loop(); //
while(1)
{
/* 获取温湿度 */
SHT2x_MeasureHM(SHT20_Measurement_T_HM, &temp);
mDelay(500);
SHT2x_MeasureHM(SHT20_Measurement_RH_HM, &humi);
/* 转化为字符串形式 */
sprintf(tempStr, "%d", temp);
sprintf(humiStr, "%d", humi);
//printf("%s %s\r\n", tempStr, humiStr);
USART2_Clear();
len = HTTP_PostPkt(HTTP_Buf, API_KEY, DEV_ID, "temp", tempStr); //HTTP组包
USART2_Write(USART2, (unsigned char *)(HTTP_Buf), len); //报文发送
printf("send HTTP msg:\r\n%s\r\n", HTTP_Buf);
mDelay(1000);
printf("rcv response:\r\n%s\r\n", usart2_rcv_buf);
USART2_Clear();
len = HTTP_PostPkt(HTTP_Buf, API_KEY, DEV_ID, "humi", humiStr); //HTTP组包
USART2_Write(USART2, (unsigned char *)(HTTP_Buf), len); //报文发送
printf("send HTTP msg:\r\n%s\r\n", HTTP_Buf);
mDelay(1000);
printf("rcv response:\r\n%s\r\n", usart2_rcv_buf);
mDelay(5000);
}
}
> atmega 328程序
> #include <Servo.h> int Echo = A5; // Echo回声脚(P2.0) int Trig =A4; // Trig 触发脚(P2.1) int Front_Distance = 0; int Left_Distance = 0;
> int Right_Distance = 0; int Left_motor_back=9; //左电机后退(IN1) int
> Left_motor_go=5; //左电机前进(IN2) int Right_motor_go=6; //
> 右电机前进(IN3) int Right_motor_back=10; // 右电机后退(IN4) int
> key=A0;//定义按键 A0 接口 int beep=A1;//定义蜂鸣器 A1 接口 int
> servopin=2;//设置舵机驱动脚到数字口2 int myangle;//定义角度变量 int pulsewidth;//定义脉宽变量
> int val; void setup() { Serial.begin(9600); // 初始化串口
> //初始化电机驱动IO为输出方式 pinMode(Left_motor_go,OUTPUT); // PIN 8 (PWM)
> pinMode(Left_motor_back,OUTPUT); // PIN 9 (PWM)
> pinMode(Right_motor_go,OUTPUT);// PIN 10 (PWM)
> pinMode(Right_motor_back,OUTPUT);// PIN 11 (PWM)
> pinMode(key,INPUT);//定义按键接口为输入接口 pinMode(beep,OUTPUT); //
> pinMode(SensorRight, INPUT); //定义右循迹红外传感器为输入 // pinMode(SensorLeft,
> INPUT); //定义左循迹红外传感器为输入 //pinMode(SensorRight_2, INPUT);
> //定义右红外传感器为输入 //pinMode(SensorLeft_2, INPUT); //定义左红外传感器为输入
> //初始化超声波引脚 pinMode(Echo, INPUT); // 定义超声波输入脚 pinMode(Trig,
> OUTPUT); // 定义超声波输出脚 pinMode(servopin,OUTPUT);//设定舵机接口为输出接口 }
> //=======================智能小车的基本动作========================= //void
> run(int time) // 前进 void run(int time) // 前进 {
> digitalWrite(Right_motor_go,HIGH); // 右电机前进
> digitalWrite(Right_motor_back,LOW);
> analogWrite(Right_motor_go,165);//PWM比例0~255调速,左右轮差异略增减
> analogWrite(Right_motor_back,0); digitalWrite(Left_motor_go,HIGH);
> // 左电机前进 digitalWrite(Left_motor_back,LOW);
> analogWrite(Left_motor_go,160);//PWM比例0~255调速,左右轮差异略增减
> analogWrite(Left_motor_back,0); delay(time * 100); //执行时间,可以调整 }
> void brake(int time) //刹车,停车 { digitalWrite(Right_motor_go,LOW);
> digitalWrite(Right_motor_back,LOW); digitalWrite(Left_motor_go,LOW);
> digitalWrite(Left_motor_back,LOW); delay(time * 100);//执行时间,可以调整 }
> void left(int time) //左转(左轮不动,右轮前进) //void left()
> //左转(左轮不动,右轮前进) { digitalWrite(Right_motor_go,HIGH); // 右电机前进
> digitalWrite(Right_motor_back,LOW); analogWrite(Right_motor_go,200);
> analogWrite(Right_motor_back,0);//PWM比例0~255调速
> digitalWrite(Left_motor_go,LOW); //左轮后退
> digitalWrite(Left_motor_back,LOW); analogWrite(Left_motor_go,0);
> analogWrite(Left_motor_back,0);//PWM比例0~255调速 delay(time * 100);
> //执行时间,可以调整 } void spin_left(int time) //左转(左轮后退,右轮前进) {
> digitalWrite(Right_motor_go,HIGH); // 右电机前进
> digitalWrite(Right_motor_back,LOW); analogWrite(Right_motor_go,150);
> analogWrite(Right_motor_back,0);//PWM比例0~255调速
> digitalWrite(Left_motor_go,LOW); //左轮后退
> digitalWrite(Left_motor_back,HIGH); analogWrite(Left_motor_go,0);
> analogWrite(Left_motor_back,150);//PWM比例0~255调速 delay(time * 100);
> //执行时间,可以调整 } void right(int time) //void right()
> //右转(右轮不动,左轮前进) { digitalWrite(Right_motor_go,LOW); //右电机后退
> digitalWrite(Right_motor_back,LOW); analogWrite(Right_motor_go,0);
> analogWrite(Right_motor_back,0);//PWM比例0~255调速
> digitalWrite(Left_motor_go,HIGH);//左电机前进
> digitalWrite(Left_motor_back,LOW); analogWrite(Left_motor_go,200);
> analogWrite(Left_motor_back,0);//PWM比例0~255调速 delay(time * 100);
> //执行时间,可以调整 } void spin_right(int time) //右转(右轮后退,左轮前进) {
> digitalWrite(Right_motor_go,LOW); //右电机后退
> digitalWrite(Right_motor_back,HIGH); analogWrite(Right_motor_go,0);
> analogWrite(Right_motor_back,150);//PWM比例0~255调速
> digitalWrite(Left_motor_go,HIGH);//左电机前进
> digitalWrite(Left_motor_back,LOW); analogWrite(Left_motor_go,150);
> analogWrite(Left_motor_back,0);//PWM比例0~255调速 delay(time * 100);
> //执行时间,可以调整 } void back(int time) //后退 {
> digitalWrite(Right_motor_go,LOW); //右轮后退
> digitalWrite(Right_motor_back,HIGH); analogWrite(Right_motor_go,0);
> analogWrite(Right_motor_back,200);//PWM比例0~255调速
> digitalWrite(Left_motor_go,LOW); //左轮后退
> digitalWrite(Left_motor_back,HIGH); analogWrite(Left_motor_go,0);
> analogWrite(Left_motor_back,200);//PWM比例0~255调速 delay(time * 100);
> //执行时间,可以调整 }
> //========================================================== void
> keysacn()//按键扫描 { int i; int val; val=digitalRead(key);//读取数字7
> 口电平值赋给val while(!digitalRead(key))//当按键没被按下时,一直循环 {
> val=digitalRead(key);//此句可省略,可让循环跑空 } while(digitalRead(key))//当按键被按下时 {
> delay(10); //延时10ms
> val=digitalRead(key);//读取数字7 口电平值赋给val
> if(val==HIGH) //第二次判断按键是否被按下
> {
> digitalWrite(beep,HIGH); //蜂鸣器响
> while(!digitalRead(key)) //判断按键是否被松开
> digitalWrite(beep,LOW); //蜂鸣器停止
> }
> else
> digitalWrite(beep,LOW); //蜂鸣器停止 } } float Distance_test() // 量出前方距离 { digitalWrite(Trig, LOW); //
> 给触发脚低电平2μs delayMicroseconds(2); digitalWrite(Trig, HIGH); //
> 给触发脚高电平10μs,这里至少是10μs delayMicroseconds(10); digitalWrite(Trig,
> LOW); // 持续给触发脚低电 float Fdistance = pulseIn(Echo, HIGH); //
> 读取高电平时间(单位:微秒) Fdistance= Fdistance/58; //为什么除以58等于厘米,
> Y米=(X秒*344)/2 // X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58 //
> Distance = Fdistance; return Fdistance; } void servopulse(int
> servopin,int myangle)/*定义一个脉冲函数,用来模拟方式产生PWM值*/ {
> pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
> digitalWrite(servopin,HIGH);//将舵机接口电平置高
> delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
> digitalWrite(servopin,LOW);//将舵机接口电平置低
> delay(20-pulsewidth/1000);//延时周期内剩余时间 } void front_detection() {
> //此处循环次数减少,为了增加小车遇到障碍物的反应速度 for(int i=0;i<=5;i++)
> //产生PWM个数,等效延时以保证能转到响应角度 {
> servopulse(servopin,90);//模拟产生PWM } Front_Distance = Distance_test(); } void left_detection() { for(int i=0;i<=15;i++)
> //产生PWM个数,等效延时以保证能转到响应角度 {
> servopulse(servopin,175);//模拟产生PWM } Left_Distance = Distance_test(); } void right_detection() { for(int i=0;i<=15;i++)
> //产生PWM个数,等效延时以保证能转到响应角度 {
> servopulse(servopin,5);//模拟产生PWM } Right_Distance = Distance_test(); }
> //=========================================================== void
> loop() { keysacn(); //调用按键扫描函数 while(1)
> {
> front_detection();//测量前方距离
> if(Front_Distance < 32)//当遇到障碍物时
> {
> back(2);//后退减速
> brake(2);//停下来做测距
> left_detection();//测量左边距障碍物距离
> right_detection();//测量右边距障碍物距离
> if((Left_Distance < 35 ) &&( Right_Distance < 35 ))//当左右两侧均有障碍物靠得比较近
> spin_left(0.7);//旋转掉头
> else if(Left_Distance > Right_Distance)//左边比右边空旷
> {
> left(3);//左转
> brake(1);//刹车,稳定方向
> }
> else//右边比左边空旷
> {
> right(3);//右转
> brake(1);//刹车,稳定方向
> }
> }
> else
> {
> run(2); //无障碍物,直行
> } } }
int temPin = A4; //设置模拟口4为LM35的信号输入端口
int soundPin = A2;
int lightPin = A1;
int a[10];
float temperature = 0; //设置temperature为浮点变量
long val=0; //设置val为长整数变量
int soundvalue,lightvalue;
float readtemp() //读取温度
{
val=analogRead(temPin);//温度传感器LM35接到模拟PIN4上;val变量为从LM35信号口读取到的数值
temperature = (val*0.0048828125*100); //把读取到的val转换为温度数值,系数一:0.00488125=5/1024,0~5V对应模拟口读数1~1024,系数二:100=1000/10,1000是毫伏与伏的转换;10是每10毫伏对应一度温升。
return temperature; //返回温度值
}
int readsound() //读取最大噪音值
{
int sound_max=0;
for(int i=0;i<10;i++)
{
a[i] = analogRead(soundPin);
sound_max=max(sound_max,a);
}
return sound_max;
}
int readlight() //采样10次光线值,返回其平均值
{
int light_sum,light_average;
int light_max = 0;
int light_min=1024;
for(int i=0;i<10;i++)
{
a = analogRead(lightPin);
light_sum=light_sum + a;
light_max=max(light_max,a);
light_min=min(light_min,a);
}
light_average = (light_max + light_min)/2;
return light_average;
}
void setup()
{
Serial.begin(9600);//设置波特率
Serial.println("Smart Environment monitor begin....");
}
void loop()
{
float tempvalue = 0;
tempvalue = readtemp();
soundvalue = readsound();
lightvalue = analogRead(lightPin);
Serial.print("now the temperature is ") ;
Serial.println(tempvalue);
Serial.print("the soundvalue is ") ;
Serial.println(soundvalue);
Serial.print("the lightvalue is ") ;
Serial.println(lightvalue);
Serial.println(); //串口分别显示读取的温度、声音、光敏值
delay(1000); //1秒刷新一次
}
作者:SakuraForever
来源:CSDN