Search code examples
c++arduinoprocessingparseint

Arduino Serial not parsing commands


I am using Processing (java) to communicate over serial to an Arduino which controls two servos and a laser. Everything works independently, however when I turn the laser on using Processing I am unable to control the servos until I turn the laser back off. Troubleshooting I've tried:

  1. Manually sending commands to the Arduino using Arduino Serial or Putty results in thethe Arduino working as expected (servo control is independent of laser status)
  2. Putting the Arduino in the serial-bridge configuration to monitor what serial commands Processing is sending to the Arduino, and it is as expected (motor positions, laser status)
  3. I am using an external power supply so I know its not a max-current-draw issue. (and it works
  4. Included delays in Processing, flushing the Arduino buffer.
  5. Used all "\n", "\r", "\r\n" combinations.

Here is my processing program :

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);
}

It has a little visualization to monitor the motor location, and basically just sends "mot_x_pos,mot_y_pos \n", and a "-1\n" to toggle the laser. example output serial stream:

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

The Arduino code parses the stream and controls the 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;
          } 
      }
   }
}

Any suggestions would be appreciated, thanks.


Solution

  • Would help if you provided the sequence of commands that's not working.

    Your Arduino code tries to read two int's, but you're only sending one with the laser command. That'll get out of synch (parseInt doesn't care about the ends of lines, it's happy to go to the next line)

    Try

    1. Having your laser button send "-1,-1" so all lines have two numbers on them
    2. Better, create a better-structured format for your lines: Start with a letter that says whether it's a servo or laser command, then read what's needed, then make sure you find a '\n', then repeat.