Qualcomm技术william hill官网
直播中

黄剑屏

7年用户 258经验值
私信 关注
[经验]

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

一.背景

上篇博客,博主给大家阐述了如何基于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: %sn", buffer);
if (size != 0)
{
// printf("Recv msg from client: %sn", buffer);
if((strcmp(buffer,left_flag))==0)
{
if(cycle>500000)
{
cycle=cycle-STEP;
// printf("Recv msg is left turnn");
set_dutycycle(cycle);
}
else
{
printf("it is left siden");
}
}
else if((strcmp(buffer,right_flag))==0)
{
if(cycle<2500000)
{
cycle=cycle+STEP;
// printf("Recv msg is right turnn");
set_dutycycle(cycle);
}
else
{
printf("it is right siden");
}
}
else
{
printf("Recv msg from client: %s,why not?n", buffer);
}
// buffer[6] = '';
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 手机控制舵机


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

更多回帖

发帖
×
20
完善资料,
赚取积分