Arduino Serial 不解析命令

Arduino Serial not parsing commands

我正在使用 Processing (java) 通过串行方式与控制两个伺服系统和一个激光器的 Arduino 进行通信。一切都独立工作,但是当我使用 Processing 打开激光时,我无法控制伺服系统,直到我关闭激光。 我尝试过的故障排除:

  1. 使用 Arduino Serial 或手动向 Arduino 发送命令 腻子使 Arduino 按预期工作(伺服控制是 独立于激光状态)
  2. 将 Arduino 置于串行桥配置中以监控什么 串行命令处理正在发送到 Arduino,它就像 预期(电机位置、激光状态)
  3. 我正在使用外部电源,所以我知道它不是 最大电流消耗问题。 (而且有效
  4. 包括处理延迟,刷新 Arduino 缓冲区。
  5. 使用了所有“\n”、“\r”、“\r\n”组合。

这是我的处理程序:

import processing.serial.*;
import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;

String ard_ser = "/dev/ttyACM0"; 

ControlIO control;
ControlDevice stick;
float px, py;
int deg_x, deg_y;
boolean trailOn;
Serial myPort;
ArrayList<PVector>  shadows = new ArrayList<PVector>();
ArrayList<PVector>  trail = new ArrayList<PVector>();

public void setup() {
  size(400, 400);
  myPort = new Serial(this, Serial.list()[0],9600);
  printArray(Serial.list());

  // Initialise the ControlIO
  control = ControlIO.getInstance(this);
  // Find a device that matches the configuration file
  stick = control.getMatchedDevice("joystick");
  if (stick == null) {
    println("No suitable device configured");
    System.exit(-1); // End the program NOW!
  }
  // Setup a function to trap events for this button
  stick.getButton("LASER").plug(this, "toggleLaser", ControlIO.ON_PRESS);
}

// Poll for user input called from the draw() method.
public void getUserInput() {
  px = map(stick.getSlider("X").getValue(), -1, 1, 0, width);
  deg_x = int(map(stick.getSlider("X").getValue(),-1,1,0,180));
  py = map(stick.getSlider("Y").getValue(), -1, 1, 0, height);
  deg_y = int(map(stick.getSlider("Y").getValue(),-1,1,0,180));
  //stick.getButton("LASER").plug(this,"toggleLaser",ControlIO.);
}

// Event handler for the Laser button
public void toggleLaser() {
  println("laser");          
  if (myPort.available()>0){
     myPort.write("-1\n");
  }
  //delay(1000);
  return;
}


public void draw() {
  getUserInput(); // Polling
  background(255, 255, 240);
  // Draw shadows
  fill(0, 0, 255, 32);
  noStroke();
  for (PVector shadow : shadows)
    ellipse(shadow.x, shadow.y, shadow.z, shadow.z);

  if ( trail.size() > 1) {
    stroke(132, 0, 0);
    for (int n = 1; n < trail.size(); n++) {
      PVector v0 = trail.get(n-1);
      PVector v1 = trail.get(n);
      line(v0.x, v0.y, v1.x, v1.y);
      v0 = v1;
    }
  }
  // Show position
  noStroke();
  fill(255, 64, 64, 64);
  ellipse(px, py, 20, 20);
  String position = str(deg_x)+','+str(deg_y)+'\n';
  if (myPort.available()>0){
      //println(position);
      myPort.write(position);
  }
  delay(10);
}

它有一点可视化来监控电机位置,基本上只是发送 "mot_x_pos,mot_y_pos \n" 和一个“-1\n”来切换激光。 示例输出串行流:

90,90\n 
50,50\n
-1\n

Arduino代码解析流并控制motors/laser:

#include <Servo.h>
bool laser = true; 
// true sets the value high (off for my transistor)
char val = 0;
const int laser_pin = 7;
int out1 = 9;    //servo pins
int out2 = 11;
boolean newData= true;
Servo servo_x;  
Servo servo_y;
int pos_x =0;
int pos_y =0;
int x_prev = 90;
int y_prev = 90;

void setup() {
 Serial.begin(9600);
 Serial.println("<Arduino is ready>");
 servo_x.attach(out1);
 servo_y.attach(out2);
 pinMode(laser_pin, OUTPUT);
 digitalWrite(laser_pin, laser); //turn laser off on startup
}

void loop(){
  while(Serial.available()>0){
     pos_x = Serial.parseInt();
     pos_y = Serial.parseInt();
     val = Serial.read();  // this catches the newline escape characters
     if ( (pos_x<0) || (pos_y<0) ){
        //toggle laser
        if(laser){
           laser = false;
        }
        else {laser = true;}
        digitalWrite(laser_pin, laser);
     }
     else if( (val == '\n') || (val == '\r')  ){
          if(pos_x != x_prev){       //only write to the motors if something has changed
              servo_x.write(pos_x);
              x_prev = pos_x;
          }
          if(pos_y != y_prev){
              servo_y.write(pos_y);   
              y_prev = pos_y;
          } 
      }
   }
}

如有任何建议,我们将不胜感激。

如果您提供了不起作用的命令序列,将会有所帮助。

您的 Arduino 代码试图读取两个 int,但您只使用激光命令发送了一个。那会失去同步(parseInt 不关心行尾,很高兴转到下一行)

尝试

  1. 让您的激光按钮发送“-1,-1”,这样所有行上都有两个数字
  2. 更好的是,为你的行创建一个 better-structured 格式:以一个说明它是伺服命令还是激光命令的字母开头,然后阅读需要的内容,然后确保找到 '\n',然后重复。