aboutsummaryrefslogtreecommitdiffstats
path: root/serial/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'serial/serial.c')
-rw-r--r--serial/serial.c203
1 files changed, 110 insertions, 93 deletions
diff --git a/serial/serial.c b/serial/serial.c
index db45fac..57b432c 100644
--- a/serial/serial.c
+++ b/serial/serial.c
@@ -1,130 +1,147 @@
1#include "path_ctrl_t.h" 1#include "serial.h"
2#include <errno.h>
3#include <fcntl.h>
4#include <stdbool.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <termios.h>
9#include <unistd.h>
10 2
11typedef unsigned char byte; 3lcm_t *lcm;
12#define MAX_BUFFER_SIZE 1024
13#define DEFAULT_SPEED 0x15
14 4
15int fd; // 轮子的串口文件描述符 5int curStatus = -1, curSpeed = 0; // 这里的速度指百分比速度
16char portname[50] = "/dev/ttyUSB0"; // 串口设备名 6double curOmega;
17char clientIP[20] = ""; 7// 临界区数据
18struct termios tty; 8pthread_mutex_t curPoseMutex;
19 9clock_t lastTime;
20bool whellInit(); 10double curPose[3] = {0, 0, 0};
21bool wheelSend(byte a, byte a_v, byte b, byte b_v);
22void speedControl(byte status, byte speed);
23void parseCmd(const lcm_recv_buf_t *rbuf, const char *channel,
24 const path_ctrl_t *msg, void *userdata);
25 11
26int main() { 12int main() {
27 if (!whellInit()) { 13 if (!whellInit()) {
28 goto err; 14 goto err;
29 } 15 }
30 lcm_t *path_lcm = lcm_create(NULL); 16 lcm = lcm_create(NULL);
31 if (!path_lcm) { 17 if (!lcm) {
32 fprintf(stderr, "Failed to create LCM\n"); 18 fprintf(stderr, "Failed to create LCM\n");
33 goto err; 19 goto err;
34 } 20 }
35 path_ctrl_t cmd; 21
36 path_ctrl_t_subscribe(path_lcm, "wheel_ctrl", parseCmd, &cmd); 22 // 订阅来自手机端的轮控消息
23 path_ctrl_t_subscribe(lcm, "wheel_ctrl", parseCmd, NULL);
24 // 订阅来自算法模块的路径规划消息
25 path_t_subscribe(lcm, "PATH", parsePath, NULL);
26 // 来自算法模块的当前位置信息
27 pthread_mutex_init(&curPoseMutex, NULL);
28 pose_t_subscribe(lcm, "CURRENTPOSE", setCurPose, NULL);
29 // 新线程,定时发送当前位置信息
30 pthread_t thread;
31 if (pthread_create(&thread, NULL, sendCurPose, NULL) != 0) {
32 fprintf(stderr, "Error: Failed to create thread\n");
33 goto err;
34 }
37 35
38 while (true) { 36 while (true) {
39 lcm_handle(path_lcm); 37 lcm_handle(lcm);
40 } 38 }
41 39
42err: 40err:
43 close(fd); 41 // close(fd);
44 return 0; 42 return 0;
45} 43}
46 44
47bool whellInit() {
48 // 打开串口
49 fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
50 if (fd < 0) {
51 fprintf(stderr, "Error opening %s: %s\n", portname, strerror(errno));
52 return false;
53 }
54
55 // 设置串口参数
56 memset(&tty, 0, sizeof tty);
57 if (tcgetattr(fd, &tty) != 0) {
58 fprintf(stderr, "Error from tcgetattr: %s\n", strerror(errno));
59 return false;
60 }
61
62 cfsetospeed(&tty, B115200); // 设置输出波特率为115200
63 cfsetispeed(&tty, B115200); // 设置输入波特率为115200
64
65 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
66 tty.c_iflag &= ~IGNBRK; // ignore break signal
67 tty.c_lflag = 0; // no signaling chars, no echo,
68 // no canonical processing
69 tty.c_oflag = 0; // no remapping, no delays
70 tty.c_cc[VMIN] = 0; // read doesn't block
71 tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
72
73 tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
74 tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
75 // enable reading
76 tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
77 tty.c_cflag |= 0;
78 tty.c_cflag &= ~CSTOPB;
79 tty.c_cflag &= ~CRTSCTS;
80
81 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
82 fprintf(stderr, "Error from tcsetattr: %s\n", strerror(errno));
83 return false;
84 }
85 return true;
86}
87
88bool wheelSend(byte a, byte a_v, byte b, byte b_v) {
89 unsigned char data[7] = {0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00};
90 byte checksum = 0;
91 data[2] = a;
92 data[3] = a_v;
93 data[4] = b;
94 data[5] = b_v;
95
96 for (int i = 0; i < 6; i++) {
97 checksum ^= data[i];
98 }
99 data[6] = checksum;
100
101 // 发送数据
102 if (write(fd, data, 7) != 7) {
103 fprintf(stderr, "Failed to write to the serial port\n");
104 return false;
105 }
106
107 printf("Data %02X %02X %02X %02X %02X %02X %02X wheelSend successfully!\n",
108 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
109 return true;
110}
111
112void parseCmd(const lcm_recv_buf_t *rbuf, const char *channel, 45void parseCmd(const lcm_recv_buf_t *rbuf, const char *channel,
113 const path_ctrl_t *msg, void *userdata) { 46 const path_ctrl_t *msg, void *userdata) {
114 byte status = msg->cmd, speed = msg->speed; 47 byte status = msg->cmd, speed = msg->speed;
48 if (curStatus == status && curSpeed == speed) {
49 return;
50 }
51
52 // 状态改变,计算新的位置
53 renewCurPose();
54
55 // 下发新的指令
115 switch (status) { 56 switch (status) {
116 case 1: 57 case 1:
117 wheelSend(0x01, speed, 0x01, speed); 58 wheelSend(0x01, speed, 0x01, speed);
59 curSpeed = speed;
60 curOmega = 0;
118 break; 61 break;
119 case 2: 62 case 2:
120 wheelSend(0x02, DEFAULT_SPEED, 0x01, DEFAULT_SPEED); 63 wheelSend(0x02, DEFAULT_SPEED, 0x01, DEFAULT_SPEED);
64 curOmega = (double)DEFAULT_SPEED * FULLSPEED / 100 / RADIUS;
65 curSpeed = 0;
121 break; 66 break;
122 case 3: 67 case 3:
123 wheelSend(0x01, DEFAULT_SPEED, 0x02, DEFAULT_SPEED); 68 wheelSend(0x01, DEFAULT_SPEED, 0x02, DEFAULT_SPEED);
69 curOmega = (double)-DEFAULT_SPEED * FULLSPEED / 100 / RADIUS;
70 curSpeed = 0;
124 break; 71 break;
125 case 0: 72 case 0:
126 default: 73 default:
127 wheelSend(0x00, 0x00, 0x00, 0x00); 74 wheelSend(0x00, 0x00, 0x00, 0x00);
75 curOmega = 0;
76 curSpeed = 0;
128 break; 77 break;
129 } 78 }
79 // 更新状态
80 curStatus = status;
81}
82
83void parsePath(const lcm_recv_buf_t *rbuf, const char *channel,
84 const path_t *msg, void *userdata) {
85 int16_t length = msg->length;
86 double v, w;
87 int8_t vWheels[2];
88 int8_t bWheels[2];
89 if (length <= 0) {
90 fprintf(stderr, "Error: Invalid path\n");
91 return;
92 }
93 v = msg->xyr[0][0];
94 w = msg->xyr[0][1];
95 if (fabs(v) <= 0.01 && fabs(w) <= 0.01) {
96 wheelSend(0x00, 0x00, 0x00, 0x00);
97 renewCurPose();
98 curSpeed = 0;
99 curOmega = 0;
100 } else {
101 vWheels[0] = (int8_t)((double)(v - w * RADIUS) / FULLSPEED * 100);
102 vWheels[1] = (int8_t)((double)(v + w * RADIUS) / FULLSPEED * 100);
103 bWheels[0] = vWheels[0] > 0 ? 0x01 : 0x02;
104 bWheels[1] = vWheels[1] > 0 ? 0x01 : 0x02;
105 wheelSend(bWheels[0], fabs(vWheels[0]), bWheels[1], fabs(vWheels[1]));
106 renewCurPose();
107 curSpeed = (int8_t)((double)v / FULLSPEED * 100);
108 curOmega = (int8_t)w;
109 }
110}
111
112void setCurPose(const lcm_recv_buf_t *rbuf, const char *channel,
113 const pose_t *msg, void *userdata) {
114 pthread_mutex_lock(&curPoseMutex);
115 curPose[0] = msg->pos[0];
116 curPose[1] = msg->pos[1];
117 curPose[2] = msg->pos[2];
118 lastTime = clock();
119 pthread_mutex_unlock(&curPoseMutex);
120}
121
122void sendCurPose() {
123 pose_t pose;
124 while (true) {
125 renewCurPose();
126 pthread_mutex_lock(&curPoseMutex);
127 pose.pos[0] = curPose[0];
128 pose.pos[1] = curPose[1];
129 pose.pos[2] = curPose[2];
130 pthread_mutex_unlock(&curPoseMutex);
131 pose_t_publish(lcm, "POSE", &pose);
132 usleep(16);
133 }
134}
135
136void renewCurPose() {
137 clock_t curTime = clock();
138 double dt = (double)(curTime - lastTime) / CLOCKS_PER_SEC;
139 double speed = (double)curSpeed * FULLSPEED / 100;
140
141 pthread_mutex_lock(&curPoseMutex);
142 curPose[0] += speed * cos(curPose[2]) * dt;
143 curPose[1] += speed * sin(curPose[2]) * dt;
144 curPose[2] += curOmega * dt;
145 lastTime = curTime;
146 pthread_mutex_unlock(&curPoseMutex);
130} \ No newline at end of file 147} \ No newline at end of file