一.背景
上篇博客,博主给大家阐述了如何基于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] = ' |