Python到Arduino,使用pyserial,突然冻结,没有错误

2024-06-25 22:58:56 发布

您现在位置:Python中文网/ 问答频道 /正文

大家好,互联网上的人们,我的团队和我遇到了一个问题,python代码将37个字符的字节数组发送到arduino。arduino控制4个直流电机和4个180度伺服系统,因此我们通过pyserial向其发送控制数据。我们正在使用两个通过usb连接到计算机的logitech extreme 3d pro操纵杆(下面的参考链接)。使用pygame,将输入转换为PWM数据,然后发送到arduino(几句之前已经解释了如何完成)。我们的问题是,该代码在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, omin, 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),0,1,500,0)
        # //preturn

        pT = map(x,-1,1,-tamp,tamp)
        lM = map(y, -1, 1, 1000, 2000)
        rM = map(y, -1, 1, 1000, 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, 1, -1, 800, 2200))

# ArmTIlt
        if round(map(self.Joy2Y, -1, 1, 1000, 2000)) > 1600 and self.S1_Data < 2200 and self.Timer % 50 == 0:
            self.S1_Data = self.S1_Data + 7
        elif round(map(self.Joy2Y, -1, 1, 1000, 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,1503,1523,1000,1500,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

还有其他问题请告诉我


Tags: andtheselftokendatagetifserial