问题描述
大家好,互联网上的人们,我和我的团队遇到了这个 python 代码的问题,该代码将 37 个字符的字节数组发送到 arduino。 arduino 控制 4 个直流电机和 4 个 180 度伺服系统,因此我们通过 pyserial 将控制数据发送给它。我们正在使用两个通过 USB 连接到计算机的罗技 Extreme 3d pro 游戏杆(参考链接如下)。使用 pygame 将输入转换为发送到 arduino 的 PWM 数据(已经在几句话前解释了如何完成)。我们的问题是代码在 MacOS 机器上完美运行,当我们尝试在 windows 或 linux 机器上运行它时(我们将使用的笔记本电脑将安装 linux,我们只是测试了 windows 以查看它是否可以工作)工作几秒钟然后冻结。当我在没有连接 4 个直流电机和 4 个伺服器(不能把它们带回家)的情况下测试这段代码时,它在所有操作系统上都能完美运行,我的同事一直告诉我这是一个编程问题,但我似乎找不到它。我附上了下面的所有代码,如果您有任何问题,请告诉我。
Python 代码
import pygame
import numpy as np
import serial
# function to map servo/motor data dependent on joystick input
def map(joy,min,max,omin,omax):
return float((((joy - min) * (omax - omin)) / (max - min)) + omin)
# same as above but used for the corner values of the joystick
def mapc(joy1,joy2,min1,max1,min2,max2,omax):
return float((((((joy1 - min1) * (omax - omin)) / (max1 - min1)) + omin) + ((((joy2 - min2) * (omax - omin)) / (max2 - min2)) + omin)) / 2)
# dum1 = input("1: ")
class JoyStickClass:
# set up the joysticks and arduino
def __init__(self):
pygame.init()
pygame.joystick.init()
self.Joy1 = pygame.joystick.Joystick(0)
self.Joy2 = pygame.joystick.Joystick(1)
self.Joy1.init()
self.Joy2.init()
self.M1_Data = 1500
self.M2_Data = 1500
self.M3_Data = 1500
self.S1_Data = 1500
self.S2_Data = 1500
self.S3_Data = 1500
self.S4_Data = 1500
self.lights = 0
# port = str(input("Enter com port (Windows: COM,MacOS: usual crap:) : "))
self.ard1 = serial.Serial('/dev/cu.usbmodem1434201',115200,timeout = 0.01)
self.startMarker = '<'
self.endMarker = '\n'
self.dividingmarker = ','
self.Timer = 0
# read the data from the joysticks and store them in their variables
def JoyRead(self):
for event in pygame.event.get():
self.Joy1X = self.Joy1.get_axis(0)
self.Joy1Y = self.Joy1.get_axis(1)
self.Joy1B1 = self.Joy1.get_button(0)
self.Joy1B6 = self.Joy1.get_button(5)
self.Joy1B7 = self.Joy1.get_button(6)
self.Joy1B8 = self.Joy1.get_button(7)
self.Joy1B3 = self.Joy1.get_button(2)
self.Joy2X = self.Joy2.get_axis(0)
self.Joy2Y = self.Joy2.get_axis(1)
self.Joy2B1 = self.Joy2.get_button(0)
self.Joy2B3 = self.Joy2.get_button(2)
self.Joy2B5 = self.Joy2.get_button(4)
self.Joy1H = self.Joy1.get_hat(0)
garbo = 1500
# Convert the data read from the joysticks to useful motor and servo data
def JoyConv(self):
self.Timer = self.Timer + 1
# Motor crap
x= self.Joy1X * 1
y=self.Joy1Y * 1
# Deadzones
if x > -.1 and x < .1:
x = 0
if y > -.1 and y < .1:
y = 0
tamp = map(abs(y),1,500,0)
# //preturn
pT = map(x,-1,-tamp,tamp)
lM = map(y,1000,2000)
rM = map(y,2000)
# //Take the amplitude of the motors
lMAmp = round(1500-lM)
lMAmp -= pT
lM = 1500 - lMAmp
rMAmp = round(1500-rM)
rMAmp += pT
rM = 1500 - rMAmp
self.M1_Data = round(lM)
self.M2_Data = round(rM)
#Up Down
if self.Joy1B7 == 1 and self.Joy1B8 == 0:
self.M3_Data = 1000
elif self.Joy1B8 == 1 and self.Joy1B7 == 0:
self.M3_Data = 2000
else:
self.M3_Data = 1500
self.S2_Data = round(map(self.Joy2X,800,2200))
# ArmTIlt
if round(map(self.Joy2Y,2000)) > 1600 and self.S1_Data < 2200 and self.Timer % 50 == 0:
self.S1_Data = self.S1_Data + 7
elif round(map(self.Joy2Y,2000)) < 1400 and self.S1_Data > 1000 and self.Timer % 50 == 0:
self.S1_Data = self.S1_Data - 7
else:
self.S1_Data = self.S1_Data
if self.Joy2B1 == 1:
self.S3_Data = 2000
else:
self.S3_Data = 1000
# Camera
if self.Joy1H == (0,-1) and self.S4_Data <= 2200 and self.Timer % 100 == 0:
self.S4_Data = self.S4_Data + 15
elif self.Joy1H == (0,1) and self.S4_Data >= 1000 and self.Timer % 100 == 0:
self.S4_Data = self.S4_Data - 15
else:
self.S4_Data = self.S4_Data
# lights
if self.Joy1H == (1,0):
self.lights = 1
elif self.Joy1H == (-1,0):
self.lights = 0
else:
self.lights = self.lights
# Send the data to the arduino
def send_to_arduino(self):
Sending_Data1 = str(self.M1_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.M2_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.M3_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.S1_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.S2_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.S3_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.S4_Data)
Sending_Data1 += self.dividingmarker
Sending_Data1 += str(self.lights)
Sending_Data1 += self.endMarker
Sending_Data_ByteArray1 = bytearray(Sending_Data1,'ascii')
# print()
if self.ard1.inWaiting():
self.ard1.flush()
self.ard1.write(Sending_Data_ByteArray1)
data = self.ard1.readline()
print(data,len(Sending_Data_ByteArray1))
# self.ard1.flush()
class MainClass:
def __init__(self):
self.joy = JoyStickClass()
def run(self):
self.joy.JoyRead()
self.joy.JoyConv()
self.joy.send_to_arduino()
main = MainClass()
while 1==1:
main.run()
Arduino 代码:
#include <Servo.h>
Servo M1;
Servo M2;
Servo M3;
Servo M4;
Servo S1;
Servo S2;
Servo S3;
Servo S4;
int VA = 0; //1000-2000
int VB = 0; //1000-2000
int VC = 0; //1000-2000
int VD = 0; //1000-2000
int VE = 0; //1000-2000
int VF = 0; //1000-2000
int VG = 0; //1000-2000
int VH = 0; //1000-2000
int VI = 0; //1 or 0
int Lights = 13;
void setup()
{
Serial.begin(115200);
Serial.println();
pinMode(Lights,OUTPUT);
M1.attach(22);
M2.attach(23);
M3.attach(24);
M4.attach(25);
S1.attach(30);
S2.attach(34);
S3.attach(38);
S4.attach(42);
}
void SerialEvent()
{
char characterBuf[39]; //stores incoming
int incomingLength = 0; //stores incoming length
char *token; //token for converting byte array to string array
int counterNum = 1;
//1503,1503,1500,1523,0
if (Serial.available()) {
// Serial.println("1");
incomingLength = Serial.readBytesUntil('\n',characterBuf,50); //calculate length of byte array
token = strtok(characterBuf,","); //convert to string
VA = atoi(token);
// Serial.println(token);
while (token != NULL) { //if token doesnt find another comma it goes back to beginning
token = strtok(NULL,"); //changes token to a string def of NULL
// Serial.println(token);
switch (counterNum) {
case 1:
VB = atoi(token);
break;
case 2:
VC = atoi(token);
break;
case 3:
VD = atoi(token);
break;
case 4:
VE = atoi(token);
break;
case 5:
VF = atoi(token);
break;
case 6:
VG = atoi(token);
break;
case 7:
VH = atoi(token);
break;
case 8:
VI = atoi(token);
break;
}
counterNum++;
}
}
}
void loop()
{
if (Serial.available()) {
SerialEvent();
M1.writeMicroseconds(VA);
M2.writeMicroseconds(VB);
M3.writeMicroseconds(VC);
M4.writeMicroseconds(VD);
S1.writeMicroseconds(VE);
S2.writeMicroseconds(VF);
S3.writeMicroseconds(VG);
S4.writeMicroseconds(VH);
if (VI == 1) {
digitalWrite(Lights,HIGH);
}
else {
digitalWrite(Lights,LOW);
}
}
Serial.print("M1: ");
Serial.print(VA);
Serial.print(" ");
Serial.print("M2: ");
Serial.print(VB);
Serial.print(" ");
Serial.print("M3: ");
Serial.print(VC);
Serial.print(" ");
Serial.print("M4: ");
Serial.print(VC);
Serial.print(" ");
Serial.print("S1: ");
Serial.print(VD);
Serial.print(" ");
Serial.print("S2: ");
Serial.print(VE);
Serial.print(" ");
Serial.print("S3: ");
Serial.print(VF);
Serial.print(" ");
Serial.print("S4: ");
Serial.print(VG);
Serial.print(" ");
Serial.print("Lights: ");
Serial.print(VH);
Serial.println();
}
请原谅任何格式错误,过去 48 小时我一直在解决这个问题,但我没有时间检查这些错误。
还参考了操纵杆的链接:
https://www.amazon.com/Extreme-3D-Pro-Joystick-Windows/dp/B00009OY9U/ref=sr_1_1?crid=1MQ474EU5M3KK&dchild=1&keywords=logitech+extreme+3d+pro+joystick&qid=1615092807&sprefix=logitech+extreme+%2Caps%2C164&sr=8-1
伺服器和电机的参考链接:
伺服:
https://www.savoxusa.com/products/savsw1210sg-waterproof-coreless-digital
电机:
http://aquaphoton.net/aquaphoton/?product=seabotix-thruster-btd150
任何其他问题请告诉我
解决方法
通过将 serial.flush 切换到 arduino 端,它解决了问题。