【问题标题】:Arduino stops working after 40 sec of serial communication with the computer与计算机进行 40 秒的串行通信后,Arduino 停止工作
【发布时间】:2021-03-03 13:11:49
【问题描述】:

我正在尝试建立一条从piarduino 的通信线路来控制电机。经过 40 45 秒的通信后,我的 arduino mega 2560(可能是克隆)停止发送数据或执行任何操作(包括写入 esc 驱动程序)。重新启动python script 可以再解决 40 秒的问题。 Tx 灯闪烁,没有其他工作。

Arduino 代码:

#include <StringSplitter.h>

#define RELAY 40

void setup() {
  Serial.begin(38400);
  pinMode(RELAY, OUTPUT);
}

bool relaysCurrState = false;
String inData = "";

void loop() {
  delay(50);
}


int* inputParser(String input){
  static int data[4];
  if(input.length() < 7){
    for(int i = 0; i < 4; i++) data[i] = 0;
    return data;
  }
  // Parsing the input that are connected by commas.
  StringSplitter *splitter = new StringSplitter(input, ',', 8);  
  int itemCount = splitter->getItemCount();
  
  for(int i = 0; i < itemCount; i++) {
    String item = splitter->getItemAtIndex(i);  
    data[i] = item.toInt();  
  }
  return data;
}

void serialEvent() {
    while (Serial.available()) {
        char inChar = (char)Serial.read();
        if (inChar == 't') {
            Serial.read();
            int* data = inputParser(inData);
            int value = data[3];
            // Relay is to change the rotating direction of the motor. Nothing too fancy
            if(value < -50) { 
              if(!relaysCurrState) {
                delay(150);
              }
              digitalWrite(RELAY, HIGH);
              relaysCurrState = true;
            }
            else if(value > 50) { 
              if(relaysCurrState) {
                delay(200);
              }
              digitalWrite(RELAY, LOW);
              relaysCurrState = false;
            }
            // Sending back the data to the pi
            Serial.println(value);
            inData = "";
        }
        else {
          inData += inChar;
        }  
    }
}

我删除了所有关于伺服的行,问题仍然存在。 Python 代码:

import time
from Joystick import Joystick
import serial

def main():
    ser = serial.Serial('/dev/ttyUSB0', 38400, timeout = .2)
    js = Joystick()
    cal_flag = False
    time.sleep(1.5)
    while True:
        if(js.option == 'fly'):
            values = js.axis_values
            ser.write(bytes(values + 't', 'ascii'))
            print('Sending... ', values)
            time.sleep(.1)
            print(ser.readline().decode('ascii'), end = '')
        elif(js.option == 'calibrate' and not cal_flag):
            ser.write(bytes('c', 'ascii'))
            print('Calibrating...\n')
            time.sleep(5)
            print('Done')
            js.option = 'fly'
        time.sleep(.2)
if __name__ == '__main__':
    main()

操纵杆模块,我用 pygame 编写的:

import pygame
import time


class Joystick(object):
    def __init__(self):
        pygame.init()
        if pygame.joystick.get_count() > 0:
            print('Joystick is connected.')
            self.joystick = pygame.joystick.Joystick(0)
            self.joystick.init()
        else:
            print('Could not find any joysticks. Trying again...')
            while pygame.joystick.get_count() == 0:
                time.sleep(1)
                pygame.event.pump()
            print('Joystick is connected.')
            self.joystick = pygame.joystick.Joystick(0)
            self.joystick.init()

        self.curr_opt = 'hold_on'


    @property
    def axis_values(self):
        max_val = 1000
        vals = list()
        pygame.event.pump()
        for i in range(5):
            if i == 1 or i == 4:
                val = -self.joystick.get_axis(i)
            else:
                val = self.joystick.get_axis(i)
            if i != 2:
                vals.append(val)
        str_vals = ','.join([str(int(x * max_val)) for x in vals])
        return str_vals  


    @property
    def calibrate_button(self):
        
        button_num = 1
        pygame.event.pump()

        start = time.time()
        curr_time = time.time()
        
        while self.joystick.get_button(button_num) and curr_time - start < .3:
            pygame.event.pump()
            curr_time = time.time()

        if curr_time - start >= .3:
            return 1 
        else:
            return 0       


    @property
    def fly_button(self):
        button_num = 7
        pygame.event.pump()
        
        start = time.time()
        curr_time = time.time()
        
        while self.joystick.get_button(button_num) and curr_time - start < .3:
            pygame.event.pump()
            curr_time = time.time()
        
        if curr_time - start >= .3:
            return 1 
        else:
            return 0


    @property
    def hold_on_button(self):

        button_num = 6
        pygame.event.pump()
        
        start = time.time()
        curr_time = time.time()
        
        while self.joystick.get_button(button_num) and curr_time - start < .3:
            pygame.event.pump()
            curr_time = time.time()
        
        if curr_time - start >= .3:
            return 1 
        else:
            return 0         


    @property
    def option(self):
        if self.calibrate_button and self.curr_opt != 'calibrate':
            self.curr_opt = 'calibrate'
            return 'calibrate'

        if self.fly_button and self.curr_opt != 'fly':
            self.curr_opt = 'fly'
            return 'fly'

        if self.hold_on_button and self.curr_opt != 'hold_on':
            self.curr_opt = 'hold_on'
            return 'hold_on'

        return self.curr_opt

    @option.setter 
    def option(self, opt):
        self.curr_opt = opt

【问题讨论】:

  • 忘了说它可能是 Serial 对象或不是我没有测试过除了我将在我测试后写的 serialEvent 之外的循环内的任何东西。
  • 您在 Arduino 上的内存不足。你用 StringSplitter 实例填充堆
  • 对处理数据有什么建议吗?其逗号分隔值将写入 ESC
  • 对 MCU 友好的编码方式

标签: python arduino raspberry-pi serial-port pyserial


【解决方案1】:

使用内存是我的错。感谢@Juraj,我想通了。我编写了另一小堆代码来拆分逗号分隔的字符串,并且只使用一个全局 int 数组来保存所有数据。 这是转换部分:

void updateValues(String data, char seperator) {
  int nums[6];
  int count = 0, last_p = 0;
  
  // Parsing comma seperated values.
  int i = 0;
  while(i < data.length()) {
    if(data[i] == ',') {
      nums[count] = data.substring(last_p, i).toInt();
      count++;
      last_p = i+1;
    }
    i++;
  }
  nums[count] = data.substring(last_p, i+1).toInt();

  // Evaluation of Shifting Movement and keep track if the robot is shifting.
  bool isShifting = false;
  for (int i = 0; i < 4; i++) {
    int value = nums[i];
    if (value > 50 || value < -50) isShifting = true;
    escValues[i] = value;
  }

  // Vertical Motors.
  int verticalPower = nums[4];
  for (int i = 4; i < 8; i++) {
    escValues[i] = verticalPower;  
  }

// If the robot is not shifting it will be able to rotate.
  if (!isShifting){
    double sensitivity = 1.0;
    int rotationPower = nums[5];
  
    short int sign = 1;
    if (rotationPower < 0) sign = -1;
    for (int i = 0; i < 4; i++) {
      escValues[i] = rotationPower * sign * sensitivity;
      sign = -sign;
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多