Posted on  Updated on 

大创小车的底盘控制

下位机采用arduino,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// 定义轮子控制引脚
#define LEFT_FRONT_PWM 3
#define LEFT_FRONT_DIR 4
#define RIGHT_FRONT_PWM 5
#define RIGHT_FRONT_DIR 6
#define LEFT_REAR_PWM 9
#define LEFT_REAR_DIR 10
#define RIGHT_REAR_PWM 11
#define RIGHT_REAR_DIR 12

void setup() {
// 设置控制引脚为输出模式
pinMode(LEFT_FRONT_PWM, OUTPUT);
pinMode(LEFT_FRONT_DIR, OUTPUT);
pinMode(RIGHT_FRONT_PWM, OUTPUT);
pinMode(RIGHT_FRONT_DIR, OUTPUT);
pinMode(LEFT_REAR_PWM, OUTPUT);
pinMode(LEFT_REAR_DIR, OUTPUT);
pinMode(RIGHT_REAR_PWM, OUTPUT);
pinMode(RIGHT_REAR_DIR, OUTPUT);

// 初始化串口通信
Serial.begin(9600);
}

void loop() {
if (Serial.available() > 0) {
// 读取串口数据
String command = Serial.readStringUntil('\n');
command.trim(); // 去除多余的空白符
if (command.length() == 5) {
// 通信测试命令
if (command == "E0000") {
Serial.println("999"); // 返回通信正常标志
return; // 不继续处理其他命令
}

// 停止所有轮子命令
if (command == "S0000") {
stopAllMotors();
Serial.println("All motors stopped");
return; // 不继续处理其他命令
}

// 解析命令
char wheel = command[0]; // 轮子标识符(A/B/C/D)
int direction = command[1] - '0'; // 方向(0或1)
int speed = command.substring(2).toInt(); // 速度(0-255)

// 限幅处理
speed = constrain(speed, 0, 200); // 限制速度在0-200之间

// 根据轮子标识符设置对应电机
switch (wheel) {
case 'A': // 左前轮
setMotor(LEFT_FRONT_PWM, LEFT_FRONT_DIR, speed, direction);
break;
case 'B': // 右前轮
setMotor(RIGHT_FRONT_PWM, RIGHT_FRONT_DIR, speed, direction);
break;
case 'C': // 左后轮
setMotor(LEFT_REAR_PWM, LEFT_REAR_DIR, speed, direction);
break;
case 'D': // 右后轮
setMotor(RIGHT_REAR_PWM, RIGHT_REAR_DIR, speed, direction);
break;
default:
Serial.println("Invalid command"); // 错误命令提示
break;
}
} else {
Serial.println("Command length error"); // 命令长度错误提示
}
}
}

// 设置电机函数
void setMotor(int pwmPin, int dirPin, int speed, int direction) {
if (pwmPin == RIGHT_FRONT_PWM || pwmPin == RIGHT_REAR_PWM) {
direction = !direction;
}
digitalWrite(dirPin, direction ? HIGH : LOW);
analogWrite(pwmPin, speed);
// 输出调试信息
Serial.print("Motor ");
Serial.print(pwmPin);
Serial.print(" set to speed: ");
Serial.print(speed);
Serial.print(", direction: ");
Serial.println(direction ? "Forward" : "Backward");
}

// 停止所有轮子的函数
void stopAllMotors() {
analogWrite(LEFT_FRONT_PWM, 0);
analogWrite(RIGHT_FRONT_PWM, 0);
analogWrite(LEFT_REAR_PWM, 0);
analogWrite(RIGHT_REAR_PWM, 0);

Serial.println("Motors stopped");
}

上位机测试遥控代码如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import serial
import keyboard
import time

# 初始化串口
SERIAL_PORT = "COM7" # 根据实际端口修改
BAUD_RATE = 9600
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)

# 初始化PWM和方向
PWM = 30 # 默认速度
DIRECTION = {
"FORWARD": 1,
"BACKWARD": 0
}

def send_command(wheel, direction, speed):
"""
向下位机发送控制命令。
:param wheel: 轮子标识符 ('A', 'B', 'C', 'D')
:param direction: 方向 (0 或 1)
:param speed: 速度 (0-255)
"""
command = f"{wheel}{direction}{speed:03d}"
ser.write((command + "\n").encode())
print(f"Sent: {command}")

def stop_all_motors():
"""发送停止所有轮子的命令。"""
ser.write("S0000\n".encode())
print("Sent: S0000 (Stop all motors)")

def control_car():
"""
通过键盘控制小车。
W: 前进
S: 后退
A: 左转
D: 右转
Q: 停止
"""
global PWM
try:
print("Use W/A/S/D to control the car, Q to stop, +/- to adjust speed.")
while True:
if keyboard.is_pressed("w"): # 前进
send_command("A", DIRECTION["FORWARD"], PWM) # 左前轮
send_command("B", DIRECTION["FORWARD"], PWM) # 右前轮
send_command("C", DIRECTION["FORWARD"], PWM) # 左后轮
send_command("D", DIRECTION["FORWARD"], PWM) # 右后轮

elif keyboard.is_pressed("s"): # 后退
send_command("A", DIRECTION["BACKWARD"], PWM) # 左前轮
send_command("B", DIRECTION["BACKWARD"], PWM) # 右前轮
send_command("C", DIRECTION["BACKWARD"], PWM) # 左后轮
send_command("D", DIRECTION["BACKWARD"], PWM) # 右后轮

elif keyboard.is_pressed("a"): # 左转
send_command("A", DIRECTION["BACKWARD"], PWM) # 左前轮
send_command("B", DIRECTION["FORWARD"], PWM) # 右前轮
send_command("C", DIRECTION["BACKWARD"], PWM) # 左后轮
send_command("D", DIRECTION["FORWARD"], PWM) # 右后轮

elif keyboard.is_pressed("d"): # 右转
send_command("A", DIRECTION["FORWARD"], PWM) # 左前轮
send_command("B", DIRECTION["BACKWARD"], PWM) # 右前轮
send_command("C", DIRECTION["FORWARD"], PWM) # 左后轮
send_command("D", DIRECTION["BACKWARD"], PWM) # 右后轮

elif keyboard.is_pressed("q"): # 停止
stop_all_motors()
time.sleep(0.2)

elif keyboard.is_pressed("+"): # 增加速度
PWM = min(255, PWM + 10)
print(f"Speed increased to: {PWM}")
time.sleep(0.2)

elif keyboard.is_pressed("-"): # 减小速度
PWM = max(0, PWM - 10)
print(f"Speed decreased to: {PWM}")
time.sleep(0.2)

time.sleep(0.1) # 防止过度占用 CPU

except KeyboardInterrupt:
print("Program terminated.")
stop_all_motors()

if __name__ == "__main__":
control_car()