基于DragonBoard 410c的遥控炮台四之远程交互(中)

    xiaoxiao2021-03-25  128

    一.背景

    上篇博客,博主给大家阐述了如何基于socket实现android手机与linux系统(DragonBoard 410c)之间通讯的功能,本文继续在此基础上整合linux端对舵机的控制逻辑。

    二.舵机控制

    1.舵机控制原理:在《http://blog.csdn.net/ad3600/article/details/59491854》这篇博客我们介绍了如何实现DragonBoard 410c 对舵机的信号控制。在export出我们所选的PWM0通道(pca9685最高支持16路并发控制)后,我们对舵机的转角控制信号实质就是对PWM信号的脉宽进行调节,其调节的指令为:

    sudo echo n > /sys/class/pwm/pwmchip0/pwm0/duty_cycle /*其中n的单位为ns(纳秒)*/

            我们可能通过改变n的值来实现对舵机的角度控制,而我们知道,舵机的转角y从0到180度之间的变化对应的PWM脉宽周期为0.5ms~2.5ms,即n的取值范围为[500000,2500000],如下:

    图1 舵机转角与PWM脉宽的关系

    三.linux服务器

    1.核心的控制:

    弄明白舵机的控制信号后,我们的控制函数编写就呼之欲出了:

    #define DRIVER_PERIOD "/sys/class/pwm/pwmchip0/pwm0/period" #define DRIVER_CYCLIE "/sys/class/pwm/pwmchip0/pwm0/duty_cycle" void open_stree()/**舵机的周期设置**/ {    char* driver_period="/sys/class/pwm/pwmchip0/pwm0/period";    char BUFF[128]={0};    int period=20000000;//set the freq to 20ms(50Hz)s    sprintf(BUFF,"sudo echo %d > %s",period,driver_period);    system(BUFF);    } int set_dutycycle(int cycle)/**舵机的脉宽设置,即转角控制信号设置**/ {    char BUFF[128]={0};    char* driver_cycle="/sys/class/pwm/pwmchip0/pwm0/duty_cycle";    sprintf(BUFF,"sudo echo %d > %s",cycle,driver_cycle);    system(BUFF); }

    2.linux服务端总的控制代码:

    #include #include #include #include #include #include #include #include #include #include #include #include #define PORT 8888 //服务器端监听端口号 #define MAX_BUFFER 1024 //数据缓冲区最大值 #define left_flag "LEFT" #define right_flag "RIGHT" #define STEP 50000 #define DRIVER_PERIOD "/sys/class/pwm/pwmchip0/pwm0/period" #define DRIVER_CYCLIE "/sys/class/pwm/pwmchip0/pwm0/duty_cycle" void open_stree() { char* driver_period="/sys/class/pwm/pwmchip0/pwm0/period"; char BUFF[128]={0}; int period=20000000;//set the freq to 20ms(50Hz)s sprintf(BUFF,"sudo echo %d > %s",period,driver_period); system(BUFF); } int set_dutycycle(int cycle) { char BUFF[128]={0}; char* driver_cycle="/sys/class/pwm/pwmchip0/pwm0/duty_cycle"; sprintf(BUFF,"sudo echo %d > %s",cycle,driver_cycle); system(BUFF); } int main() { struct sockaddr_in server_addr, client_addr; int server_sockfd, client_sockfd; int size, write_size; char buffer[MAX_BUFFER]; char *buffer_report="Succee"; int cycle=1500000; open_stree(); set_dutycycle(cycle); //init mid station if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) //创建Socket { perror("Socket Created Failed!\n"); exit(1); } printf("Socket Create Success!\n"); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(PORT); bzero(&(server_addr.sin_zero), 8); int opt = 1; int res = setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //设置地址复用 if (res < 0) { perror("Server reuse address failed!\n"); exit(1); } if (bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) //绑定本地地址 { perror("Socket Bind Failed!\n"); exit(1); } printf("Socket Bind Success!\n"); if (listen(server_sockfd, 5) == -1) //监听 { perror("Listened Failed!\n"); exit(1); } printf("Listening ....\n"); socklen_t len = sizeof(client_addr); printf("waiting connection...\n"); if ((client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len)) == -1) //等待客户端连接 { perror("Accepted Failed!\n"); exit(1); } printf("connection established!\n"); printf("waiting message...\n"); while (1) { memset(buffer, 0, sizeof(buffer)); //清空数据缓冲区 if ((size = read(client_sockfd, buffer, MAX_BUFFER)) == -1) //读取客户端的数据 { perror("Recv Failed!\n"); exit(1); } printf("1111 Recv msg from client: %s\n", buffer); if (size != 0) { // printf("Recv msg from client: %s\n", buffer); if((strcmp(buffer,left_flag))==0) { if(cycle>500000) { cycle=cycle-STEP; // printf("Recv msg is left turn\n"); set_dutycycle(cycle); } else { printf("it is left side\n"); } } else if((strcmp(buffer,right_flag))==0) { if(cycle<2500000) { cycle=cycle+STEP; // printf("Recv msg is right turn\n"); set_dutycycle(cycle); } else { printf("it is right side\n"); } } else { printf("Recv msg from client: %s,why not?\n", buffer); } // buffer[6] = '\0'; if ((write_size = write(client_sockfd, buffer_report,6)) > 0) //把收到的数据回发给客户端 { ("Sent msg to client successfully!\n"); } } } close(client_sockfd); //关闭Socket close(server_sockfd); return 0; }

    四.实测效果:

    图2 手机控制舵机

      通过手机输入数值,我们就可以简单地通过远程控制我们的舵机转动,当然这样输入数值的方式不大方便,在下一节,我们会详细阐述如何解决这个问题。

    转载请注明原文地址: https://ju.6miu.com/read-8714.html

    最新回复(0)