TCP机械臂测试——8.13

1.通过w(红色臂角度增大)s(红色臂角度减小)d(蓝色臂角度增大)a(蓝色臂角度减小)按键控制机械臂

注意:关闭计算机的杀毒软件,电脑管家,防火墙

1)基于TCP服务器的机械臂,端口号是8888, ip是Windows的ip;

查看Windows的IP:按住Windows+r 按键,输入cmd , 输入ipconfig

2)点击软件中的开启监听;

3)机械臂需要发送16进制数,共5个字节,协议如下

1、0xff         0x02         x         y         0xff

2、0xff:起始结束协议,固定的;

3、0x02:控制机械手臂协议,固定的;

4、x:指定要操作的机械臂

           0x00 红色摆臂

           0x01 蓝色摆臂

5、y:指定角度

代码:

#include <myhead.h>
#define SER_PORT 8888          //服务器端口号
#define SER_IP "192.168.0.135" //服务器ip地址
#define CLI_PORT 6666          //客户端端口号
#define CLI_IP "192.168.0.101" //客户端ip地址

int main(int argc, char const *argv[])
{
    //1. 创建用于通信的套接字文件描述符
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success\n");

    //将端口号快速重用
    int reuse =1;
    if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1)
    {
        perror("stesockopt error");
        return -1;
    }
    printf("端口号快速重用成功\n");

    //2.绑定IP地址和端口号
    //2.1 填充地址信息结构体
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;                //通信域
    cin.sin_port = htons(CLI_PORT);          //端口号
    cin.sin_addr.s_addr = inet_addr(CLI_IP); //IP地址

    //2.2绑定工作
    if (bind(cfd, (struct sockaddr *)&cin, sizeof(cin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");

    //3. 连接服务器
    //3.1 填充服务器地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;                //通信域
    sin.sin_port = htons(SER_PORT);          //服务器端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP); //服务器IP地址

    //3.2 开始连接
    if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("connect error");
        return -1;
    }
    printf("连接成功\n");

    //准备数据
    char rbuf[5] = {0xff, 0x02, 0x00, 0x00, 0xff}; //16进制
    char bbuf[5] = {0xff, 0x02, 0x01, 0x5A, 0xff};

    //发送给服务器,以初始化机械臂
    send(cfd, rbuf, sizeof(rbuf), 0);
    sleep(1);
    send(cfd, bbuf, sizeof(bbuf), 0);

    printf("按q可退出\n");
    while (1)
    {
        char x = getchar();
        getchar();      //吸收回车
        if (x == 'w')
        {
            if (rbuf[3] > -90 && rbuf[3] <=85)
            {
                rbuf[3] = rbuf[3] + 5;
                send(cfd, rbuf, sizeof(rbuf), 0);
            }
        }
        else if (x == 's')
        {
            if (rbuf[3] >= -85 && rbuf[3] < 90)
            {
                rbuf[3] = rbuf[3] - 5;
                send(cfd, rbuf, sizeof(rbuf), 0);
            }
        }
        else if (x == 'a')
        {
            if (bbuf[3] >= 5 && bbuf[3] < 180)
            {
                bbuf[3] = bbuf[3] - 5;
                send(cfd, bbuf, sizeof(bbuf), 0);
            }
        }
        else if (x == 'd')
        {
            if (bbuf[3] > -0 && bbuf[3] <= 175)
            {
                bbuf[3] = bbuf[3] + 5;
                send(cfd, bbuf, sizeof(bbuf), 0);
            }
        }
        else if (x == 'q')
        {
            break;
        }
        else
        {
            printf("您输入的命令有误\n");
        }
    }

    //关闭套接字
    close(cfd);
    return 0;
}

演示图片:

虽然代码可行,但每次操作都要按一次回车,会有点麻烦,本文只提供最基础写法。

新增代码

#include <myhead.h>
#include <linux/input.h>
#define SER_PORT 8888          //服务器端口号
#define SER_IP "192.168.0.135" //服务器ip地址
#define CLI_PORT 6666          //客户端端口号
#define CLI_IP "192.168.0.147" //客户端ip地址

int main(int argc, char const *argv[])
{
    //1. 创建用于通信的套接字文件描述符
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success\n");

    //将端口号快速重用
    int reuse = 1;
    if (setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
    {
        perror("stesockopt error");
        return -1;
    }
    printf("端口号快速重用成功\n");

    //打开键盘驱动文件
    int fd = open("/dev/input/event1", O_RDONLY);
    if (fd == -1)
    {
        perror("open error");
        return -1;
    }

    //定义容器接收数据
    struct input_event ie;            //关于键盘的文件结构体

   
    //3. 连接服务器
    //3.1 填充服务器地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;                //通信域
    sin.sin_port = htons(SER_PORT);          //服务器端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP); //服务器IP地址

    //3.2 开始连接
    if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("connect error");
        return -1;
    }
    printf("连接成功\n");

    //准备数据
    char rbuf[5] = {0xff, 0x02, 0x00, 0x00, 0xff}; //16进制
    unsigned char bbuf[5] = {0xff, 0x02, 0x01, 0x5A, 0xff};

    //发送给服务器,以初始化机械臂
    send(cfd, rbuf, sizeof(rbuf), 0);
    sleep(1);
    send(cfd, bbuf, sizeof(bbuf), 0);

    while (1)
    {
        //从驱动文件中读取数据
        read(fd, &ie, sizeof(ie));
        //对输入的数据进行判断
        switch (ie.code * ie.value)
        {
        case 32: //表示按下了d键
        {
            if (bbuf[3] > -0 && bbuf[3] <= 175)
            {
                bbuf[3] = bbuf[3] + 5;
                send(cfd, bbuf, sizeof(bbuf), 0);
            }
        }
        break;
        case 31: //表示按下了s键
        {
            if (rbuf[3] >= -85 && rbuf[3] < 90)
            {
                rbuf[3] = rbuf[3] - 5;
                send(cfd, rbuf, sizeof(rbuf), 0);
            }
        }
        break;
        case 30: //表示按下了a键
        {
            if (bbuf[3] >= 5 && bbuf[3] < 180)
            {
                bbuf[3] = bbuf[3] - 5;
                send(cfd, bbuf, sizeof(bbuf), 0);
            }
        }
        break;
        case 17: //表示按下了w键
        {
            if (rbuf[3] > -90 && rbuf[3] <= 85)
            {
                rbuf[3] = rbuf[3] + 5;
                send(cfd, rbuf, sizeof(rbuf), 0);
            }
        }
        break;
        }
    }

    //关闭套接字
    close(cfd);

    return 0;
}

修改了一下,利用直接读取驱动盘(键盘)文件,可以省略按回车的步骤。

在运行a.out文件时,前面要加上 sudo ,即 sudo ./a.out

思维导图:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值