这篇写上位机测试软件,为后面的测试做个铺垫。
上位机测试的程序主要是为协议测试做个包装。
程序和控制过程也是尽量简化写了,以测试协议为主,中间有部分协议没有实现(应答部分)。
主目录:
http://blog.csdn.net/DFSAE/article/details/78715815
本篇目录
一.实现效果
二.开发环境
三.界面
四.代码
1.socket通信
2.普通按键/控件响应
3.摄像头显示
五.注意事项
一.实现效果
完成最简单的界面,实现的效果就是按协议的内容对硬件进行控制。需要对摄像头进行控制,显示摄像头采集到的显示内容,电机控制。
二.开发环境
这里简单的用QT做了,VS平台下,只是做个测试而已,如果有别的需求应用可以另外做。
三.界面
界面风格按简单的做了。
这里电机控制要说明一下:
小车电机控制的感觉和开车的操作比较类似,这里简化成一个上下的滑块和左右的滑块,再附加6个档位。其中:
1>.上下滑块有3个档,分别代表前进后退和停止。
2>.6个档位,0档位停车,其他从1-5速度不断递增。但是必须只有上下滑块档位处于前进或后退是才会生效,否则无效。如果要真实做的话可以用一个按键按住的时间来分辨到达哪个档位了。另外,最好控制做档位突变,特别是突然反转。因为硬件上没有对突变的控制做保护,这样很可能会照成硬件的损坏。
3>.左右滑块是控制方向的:0-180度间的输入量,但硬件上只是一个线性的控制,并不一定正确。
4>.直接PWM-方向设置的测试没有增加上。真正在做的时候其实取一种控制方式就好,不要混着控制。
5>.PWM-方向查询功能也没做。
6>.摄像头端口改变也没做。
四.代码
很早之前写的程序,复制粘贴出来的,看着麻烦了点。具体代码放在放上:
1.socket通信
socket基础操作包括:连接,断开,发送,接收等。windows下需要加载加载 ws2_32.dll库。
socket原始操作参考:http://c.biancheng.net/cpp/html/3031.html
#pragma comment(lib, "ws2_32.lib")
struct socket_info
{
public:
char* ip;
int port;
};
class monConnector
{
private:
socket_info sInfo; //ip和端口号
bool connect_sta;
SOCKET sock;
static int nLink;
public:
monConnector(socket_info *mon_sInfo);
~monConnector();
int mon_connect();//连接ip
void mon_close();//断开连接
bool get_connetSta()//查看连接状态
{return connect_sta;}
int rebindIP(socket_info *mon_sInfo);//重新绑定IP
int mon_recv(char *recv_buf, int size);//接收函数
int mon_send(char *send_buf, int size);//发送函数
};
//连接监控终端
int monConnector::mon_connect()
{
//创建套接字
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//向服务器发起请求
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(sInfo.ip);
sockAddr.sin_port = htons(sInfo.port);
if (-1 == connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR)))
connect_sta = false;
else
connect_sta = true;
return connect_sta;
}
//关闭连接
void monConnector::mon_close()
{
if (nLink > 0)
{
closesocket(sock);
nLink--;
if (nLink == 0)
{
WSACleanup(); //终止使用 DLL
}
}
}
//接收
int monConnector::mon_recv(char *recv_buf, int size)
{
if(connect_sta == true)
return recv(sock, recv_buf, size, NULL);
else
{
ERROR_OUTPUT("not connect!");
return -1;
}
}
//发送
int monConnector::mon_send(char *send_buf, int size)
{
if(connect_sta == true)
return send(sock, send_buf, size, 0);
else
{
ERROR_OUTPUT("not connect!");
return -1;
}
}
2.普通按键/控件响应
接着是界面按键的响应回调函数,或者是滑块滑动之后的回调函数。为了简化,直接输入发送测试的协议。如下示例:
void monitor::on_speed0Btn()
{
speed = 0;
char sendbuff1[] = {0x7f, 0x00, 0x06, 0x10, 0x11, 0x00, 0x00, 0x65};
sendbuff1[5] = ui.horizontalSlider->value();
comm_conct.mon_send(sendbuff1,sizeof(sendbuff1));
}
3.摄像头显示
摄像头显示的代码参考资料:
blog.csdn.net/qq_21792169/article/details/51147585
基本直接用了。不过这里的算法还存在问题,大概是读到数据长度和实际字节长度不一致的问题,所以会导致丢帧。懒得管他,为了方便,直接每次重新请求(我把socket连接也放一起了,这里可以改掉)。
获取图片的方法,我在QT中设了一个定时器,然后在定时器到时的回调函数里进行请求,再用label标签进行图片显示。
void monitor::timerDone()
{
int len = 0;
socket_info tcp_link = {"192.168.55.1", 8090};
monConnector connector(&tcp_link);
v1 = new video(&connector);
socket_info tcp_link2 = {"192.168.55.1", 8070};
monConnector connector2(&tcp_link2);
v2 = new video(&connector2);
v1->init();
len = v1->get_videoStream(buff);
if (len > 2000)
{
img1.loadFromData((unsigned char*)buff, len, "JPG");
if (!img1.isNull())
ui.picture->setPixmap(QPixmap::fromImage(img1));
}
v2->init();
len = v2->get_videoStream(buff);
if (len > 2000)
{
img2.loadFromData((unsigned char*)buff, len, "JPG");
if (!img2.isNull())
ui.picture2->setPixmap(QPixmap::fromImage(img2));
}
delete v1;
delete v2;
}