巡检机器人

当前位置:前位置:首页 > 巡检机器人
全部 615

巡检机器人有哪些优势及特点-移动机器人教授-移动机器人模组-如何在Linux下给zigbeeCC2530实现上位机

时间:2022-02-25   访问量:0
0、前言


粉丝提问


项目框架

,其实就,内容分为几块:

下位机,通过串口与上位机相连;

下位机要能够接收上位机下发的命令,并解析这些命令;

下位机能够根据这些命令配置对应的外设、读取对应的传感器的数据上传到上位机;

主程序串口操作模块:通过串口下发命令或者读取下位机上传的数据信息;

:接收远程服务器下发的命令,并将下位机采集的数据上传到服务器。

整体看来,这个相当于是一个小的项目了,内容难度都比较大,下面我们会分为几篇独立的文章来讲解。

本篇只讨论如何给下位机编写一个简单的上位机。

一、环境简介1.软硬件环境

下位机:CC2530OS:vmware+ubuntu

在这里彭老师采用的是CC2530,读者也可以采用其他的板子,我们只需要该板子有串口,可以和PC通信,led灯、继电器以及可以采集数据的传感器即可。

2.硬件连接图

硬件连接图如下:


物理连接图

该款CC2530已经集成了CH340芯片,usb线连接电脑,即可被识别。

3.pc下识别串口

如果该串口被PC获取,名字为COMn【n为某整数】。


windows下串口

4.ubuntu下识别串口

首先需要vmware抓取串口【windows抓取要么被vmware抓取】,按下图所示,点击连接即可:


虚拟机抓取串口

但是往往ubuntu中没有ch340的驱动,经过实际测试,ubuntu14及之前的版本都没有这个驱动,ubuntu16以上的版本有这个驱动。

如果没有ch340驱动可以用以下方法安装对应的驱动:

1make2sudomakeload3ls/dev/ttyUSB0


ubuntu安装串口驱动

按照上述步骤,会生成设备文件**/dev/ttyUSB0**。

ls/dev/ttyUSB0-lcrw-rw----1rootdialout188,0Jan1505:45/dev/ttyUSB0

c:字符设备rw-rw----:文件操作权限
188,0:主次设备号

3、4节提到的usb转串口驱动和linux下驱动源码后台【GH】回复

ch340

即可获得


驱动

【注意】

如果是其他开发板,自行安装其他的串口驱动。

二、模块设计

上位机和下位机的通信往往都是通过串口,linux下往往生成字符设备ttyUSB0【有的是ttyS0】,操作串口设备就只需要操作该字符设备即可。

下面我们设计上下位机的软件模块。

1.信令

设计上位机,首先需要设计上位机下发给下位机的指令格式,上位机按照该指令格式发送命令给下位机,下位需严格按照该指令格式进行解析指令。


信令格式

含义如下:

device:要操作的设备

data:对应的设备及其额外的数据

CRC:校验码

#:信令终止符

信令格式可以根据需要扩展或者精简。

其中device定义如下【可以根据实际情况进行扩展】:

#defineDEV_ID_LED_ON0X1#defineDEV_ID_LED_OFF0X2#defineDEV_ID_DELAY0X3#defineDEV_ID_GAS0X4

【注意】

为便于理解,我们暂不考虑效率问题。

2.上传数据

下位机需要采集传感器的数据并通过串口上传,数据结构定义如下:

structdata{unsignedchardevice;unsignedcharcrc;unsignedshortdata;};
device设备

data采集的数据

crc校验码

3.功能模块

现在就可以开始设计软件的各个功能模块了。

下位机


下位机流程图

下位主要任务就是循环接收上位机通过串口下发的数据,然后解析该指令内容,操作对应的硬件。

上位机


上位机

上位机主要任务是打印菜单,由用户针对菜单做出选择,然后按照指令格式封装命令,并通过串口将该命令下发给下位机。

三、下位机功能函数

cc2530的操作原理,本文不讨论,如果是其他开发板,只需要修改串口操作函数。

1.LED初始化
/*****************************************************************************名称:InitLed()*功能:设置LED灯相应的IO口*入口参数:无*出口参数:无****************************************************************************/voidInitLed(void){P1DIR|=0x01;//定义为输出口LED1=0;}
2.初始化UART
/*****************************************************************名称:InitUart()*功能:串口初始化函数*入口参数:无*出口参数:无*****************************************************************/voidInitUart(void){PERCFG=0x00;//外设控制寄存器USART0的IO位置:0为P0口位置1P0SEL=0x0c;//P0_2,P0_3用作串口(外设功能)P2DIR&=~0xC0;//P0优先作为UART0U0CSR|=0x80;//设置为UART方式U0GCR|=11;U0BAUD|=216;//波特率设为115200UTX0IF=0;//UART0TX中断标志初始置位0U0CSR|=0x40;//允许接收IEN0|=0x84;//开总中断允许接收中断}
3.串口发送函数
/***********************************************************************名称:UartSendString()*功能:串口发送函数*入口参数:Data:发送缓冲区len:发送长度*出口参数:无***********************************************************************/voidUartSendString(char*Data,intlen){uinti;for(i=0;ilen;i++){U0DBUF=*Data++;while(UTX0IF==0);UTX0IF=0;}}
4.串口中断处理函数
/***********************************************************************名称:UART0_ISR(void)串口中断处理函数*描述:当串口0产生接收中断,将收到的数据保存在RxBuf中**********************************************************************/#pragmavector=URX0_VECTOR__interruptvoidUART0_ISR(void){URX0IF=0;//清中断标志RxBuf=U0DBUF;}
5.烟雾传感器数据读取
/*****************************************************************名称:myApp_ReadGasLevel()*功能:烟雾传感器数据读取*入口参数:无*出口参数:无*****************************************************************/uint16myApp_ReadGasLevel(void){uint16reading=0;/*Enablechannel*/ADCCFG|=0x80;/*writingtothisregisterstartstheextraconversion*/ADCCON3=0x87;/*Waitfortheconversiontobedone*/while(!(ADCCON1&0x80));/*Disablechannelafterdoneconversion*/ADCCFG&=(0x80^0xFF);/*Readtheresult*/reading=ADCH;reading|=(int16)(ADCH8);reading=8;return(reading);}
6.LED灯控制函数
/*****************************************************************名称:led_opt()*功能:LED灯控制函数*入口参数:RxData:接收到的指令flage:led的操作,点亮或者关闭*出口参数:无*****************************************************************/voidled_opt(charRxData[],unsignedcharflage){switch(RxData[1]){case1:LED1=(flage==DEV_ID_LED_ON)?ON:OFF;break;/*TBDforled2led3*/default:break;}return;}
7.主程序
/*****************************************************************************主程序入口函数****************************************************************************/voidmain(void){CLKCONCMD&=~0x40;//32MHZ晶振while(CLKCONSTA&0x40);//等待晶振稳定为32MCLKCONCMD&=~0x47;//32MHZInitLed();//设置LED灯相应的IO口InitUart();//串口初始化函数UartState=UART0_RX;//串口0默认处于接收模式memset(RxData,0,SIZE);while(1){//接收状态if(UartState==UART0_RX){//读取数据,遇到字符#或者缓冲区字符数量超过4就设置UartState为CONTROL_DEV状态if(RxBuf!=0){//以#为结束符,一次最多接收4个字符if((RxBuf!=#)&&(count4)){RxData[count++]=RxBuf;}else{//判断数据合法性,防止溢出if(count=4){//计数清0count=0;//清空接收缓冲区memset(RxData,0,SIZE);}else{//进入发送状态UartState=CONTROL_DEV;}}RxBuf=0;}}//控制控制外设状态if(UartState==CONTROL_DEV){//判断接收的数据合法性//RxData[]:|device|data|crc|#|//check_crc:crc=device^data//if(RxData[2]==(RxData[0]^RxData[1])){switch(RxData[0]){caseDEV_ID_LED_ON:led_opt(RxData,DEV_ID_LED_ON);break;caseDEV_ID_LED_OFF:led_opt(RxData,DEV_ID_LED_OFF);break;caseDEV_ID_DELAY:break;caseDEV_ID_GAS:send_gas();break;default:break;}}UartState=UART0_RX;count=0;//清空接收缓冲区memset(RxData,0,SIZE);}}}
四、上位机功能函数

结构体

#defineDEV_ID_LED_ON0X1#defineDEV_ID_LED_OFF0X2#defineDEV_ID_DELAY0X3#defineDEV_ID_GAS0X4structdata{unsignedchardevice;unsignedcharcrc;unsignedshortdata;};

函数

voiduart_init(void){intnset1,nset2;serial_fd=open(/dev/ttyUSB0,O_RDWR);if(serial_fd==-1){printf(open()error\n);exit(1);}nset1=set_opt(serial_fd,115200,8,N,1);if(nset2==-1){printf(set_opt()error\n);exit(1);}}intMenu(){intoption;system(clear);printf(\n\t\t************************************************\n);printf(\n\t\t**ALARMSYSTERM**\n);printf(\n\t\t**1----LED**\n);printf(\n\t\t**2----GAS**\n);printf(\n\t\t**0----EXIT**\n);printf(\n\t\t************************************************\n);while(1){printf(Pleasechoosewhatyouwant:);scanf(%d,&option);if(option0||option2)printf(\t\tchooseerror!\n);elsebreak;}returnoption;}//RxData[]:|device|data|crc|#|voidled(){intlednum=0;intonoff;charcmd[4];//选择led灯while(1){printf(inputlednumber:[12]\n#);scanf(%d,&lednum);//checkif(lednum1||lednum2){printf(invalidlednumber\n);system(clear);continue;}else{break;}}printf(operation:1on,0off\n);scanf(%d,&onoff);if(onoff==1){cmd[0]=DEV_ID_LED_ON;}elseif(onoff==0){cmd[0]=DEV_ID_LED_OFF;}else{printf(invalidlednumber\n);return;}cmd[1]=lednum;//fulfillcrcareacmd[2]=cmd[0]^cmd[1];cmd[3]=#;//表示结束符tcflush(serial_fd,TCIOFLUSH);inti=0;for(i=0;i4;i++){printf(%d,cmd[i]);}printf(\n);write(serial_fd,&cmd,sizeof(cmd));sleep(1);}//RxData[]:|device|data|crc|#|voidgas(){intlen;unsignedshortGasLevel;structdatamsg;chargas[4]={0};charcmd[4];cmd[0]=DEV_ID_GAS;cmd[3]=#;//表示结束符write(serial_fd,&cmd,sizeof(cmd));sleep(1);len=read(serial_fd,&msg,sizeof(structdata));//转换读取的gas数据格式GasLevel=;gas[0]=GasLevel/100+0;gas[1]=GasLevel/10+0;gas[2]=GasLevel+0;printf(%s\n,gas);getchar();}voidrun(){intx;while(1){x=Menu();switch(x){case1:led();break;case2:gas();break;case0:printf(\n\t\texit!\n\n);close(serial_fd);exit(0);default:fg=1;break;}if(fg)break;}}intmain(){uart_init();run();return0;}
五、运行结果1.上位机运行界面


主菜单

2.点亮led灯

点亮led1:


点亮led1

3.灭灯


熄灭led1

4.读取烟雾传感器数据


获取烟雾数据

烟雾的数据是

079

,可以

点根华子

,你会发现每次读取的值都是在变化。

OK!至此为止,一个简易的CC2530上位机我们就编写完毕,如果想将从串口获取的数据的值发送到远端服务器,后续文章我们将继续讨论。

关注公号:

一口Linux

后台回复,【

cc2530上位机

】即可获得源码。

上一篇:智能巡检机器人创新设计-移动机器人的发展领域-巡检机器人使用案例-MIT开发符合人的行为规则的移动机器人

下一篇:移动机器人差速控制原理-桁架机器人机械手维护保养法则

返回顶部