Arduino Proccessing IDE: How to print & write XYZ position only once?

Hello,
I am working on a delta robot controlled with stepper motors through arduino uno.
I found a code online (Code) that allows me to use Arduino processing IDE to control the motors. But I am very new to arduino so I am facing some difficulties.
My problem: I am trying to send position XYZ to my arduino but there is a problem I am facing. when I am not moving the end effector to a new position it keeps sending & printing the old position to my arduino which I no longer need and that causes my stepper motors to keep on moving even when the end effector is stand still at the same orginal position.
The following is a picture the proccessing IDE program and as you can see the end effector is the area highlighted in red:

Right now it is printing the postion it is on several times and when I move the end effector to a new position it keeps on printing and sending this position several times as well until I move to next postion. Here is a photo of the positions being repeatedly printed in the processing IDE:

Here is the proccessing IDE code:

import processing.serial.*;

Serial myPort;    // The serial port:

int XXX = 0; // x zero
int YYY = 0; // y zero
int ZZZ = -180; // z zero (the robot is upsidedown)
int serialBegin = 255;


void setup() {
  size(600,600);

  // open serial port
  //myPort = new Serial(this, Serial.list()[1], 9600);
  myPort = new Serial(this, "COM4", 9600);
  frameRate(100);
  noCursor();
}

void draw() {

  background(255);

  //triangle draw
  triangle(width/2, height, 0, 200, width, 200);

  strokeWeight(3);

  //line draw
  line(300,200,mouseX,mouseY);
  line(150,400,mouseX,mouseY);
  line(450,400,mouseX,mouseY);

  // X and y value are scaled in order to fit the robot space work 
  XXX=round(float((mouseX-300))*2/5);
  YYY=round(float((mouseY-300))*2/5);

  // if mouse is pressed the Z value change
  if (mousePressed && (mouseButton == LEFT)) {
    ZZZ -= 1;
  }
  if (mousePressed && (mouseButton == RIGHT)) {
    ZZZ += 1;
  }

  String xPos;
  String yPos;
  String zPos;


  //write X value in serial port
  xPos="X";
  if (XXX > 0) 
    xPos += '+';
  else 
    xPos += '-';
  if (abs(XXX) < 100)
    xPos += '0';
  if (abs(XXX) < 10)
    xPos += '0';
  xPos += abs(XXX);


  // write Y value in serial port
  yPos="Y";
  if (YYY > 0) 
    yPos += '+';
  else 
    yPos += '-';
  if (abs(YYY) < 100)
    yPos += '0';
  if (abs(YYY) < 10)
    yPos += '0';
  yPos += abs(YYY);

  // write Z value in serial port
  zPos="Z";
  if (ZZZ > 0) 
    zPos += '+';
  else 
    zPos += '-';
  if (abs(ZZZ) < 100)
    zPos += '0';
  if (abs(ZZZ) < 10)
    zPos += '0';
  zPos += abs(ZZZ);

  // write x,y,z in the serial port
  myPort.write(xPos);
  myPort.write(yPos);
  myPort.write(zPos);
  
  // write x,y,z in the monitor
  
  println(xPos);
  println(yPos);
  println(zPos);
}

I am trying to use if condition to solve this problem and I also tried to search for a solution online but I still can not find one so far. so I thought I would ask here maybe someone have a solution that will help me and save me some time.

Here is my attempt that I am working on currently but of course this attempt wont work yet because variables xPos, yPos, zPos are not initialized.

  String xPos;
  String yPos;
  String zPos;

//write X value in serial port
  if(xPos!="X"){
  xPos="X";
  if (XXX > 0) 
    xPos += '+';
  else 
    xPos += '-';
  if (abs(XXX) < 100)
    xPos += '0';
  if (abs(XXX) < 10)
    xPos += '0';
  xPos += abs(XXX);
  }

  // write Y value in serial port
  if(yPos!="y"){
  yPos="Y";
  if (YYY > 0) 
    yPos += '+';
  else 
    yPos += '-';
  if (abs(YYY) < 100)
    yPos += '0';
  if (abs(YYY) < 10)
    yPos += '0';
  yPos += abs(YYY);
  }
  
  // write Z value in serial port
  if(zPos!="z"){
  zPos="Z";
  if (ZZZ > 0) 
    zPos += '+';
  else 
    zPos += '-';
  if (abs(ZZZ) < 100)
    zPos += '0';
  if (abs(ZZZ) < 10)
    zPos += '0';
  zPos += abs(ZZZ);
  }

  // write x,y,z in the serial port
  myPort.write(xPos);
  myPort.write(yPos);
  myPort.write(zPos);
  
  // write x,y,z in the monitor
  
  println(xPos);
  println(yPos);
  println(zPos);
}

not sure exactly where this is done in your code.

but shouldn't you only send something if the position has changed or on the arduino, ignore position updates if they haven't changed?

If you look at the xPos part of the code alone, you could see that it keeps storing the value "X" in itself even if it is the same value as the previous one and then it sends it to my arduino and print it on the IDE. Hence, the same value keeps on repeating as long as I am not moving my end-effector.

String xPos;
 //write X value in serial port
  xPos="X";
  if (XXX > 0) 
    xPos += '+';
  else 
    xPos += '-';
  if (abs(XXX) < 100)
    xPos += '0';
  if (abs(XXX) < 10)
    xPos += '0';
  xPos += abs(XXX);

 myPort.write(xPos);
 println(xPos);

Yes this is exactly what I am trying to do :smiley: but I am not sure how yet.

what about only doing the stuff to update the position when a (??) mouse button is pressed?

if( abs( xPos - lastxPos) > threshold){
 myPort.write(xPos);
lastxPos = xPos);
}

Fill in the variables for threshold and lastxPos.

1 Like

@Grumpy_Mike Thanks a lot for you response :heart:
But could you please elaborate a little more on what the variables for threshold and lastxPos should be ?

@gcjr

I am not sure if I understand your question correctly, if you are asking about the following part of the code: (what it does is that it updates the z position when mouse is pressed because the drawing is plannar and this would be the only way to update the z position)

  // if mouse is pressed the Z value change
  if (mousePressed && (mouseButton == LEFT)) {
    ZZZ -= 1;
  }
  if (mousePressed && (mouseButton == RIGHT)) {
    ZZZ += 1;
  }

But if you are suggesting that I should use a simlar approach to update all values when a certain button is pressed. then thanks for you suggestion I will try to do that. But it is important to note that z position only changes when pressed and even though it still repeats the same old value if not pressed as shown in this photo:

Screenshot (679)

The lastxPos is a variable used to hold the last value of xPos you printed.
The threshold is a value by which your current value of xPos has to change from the last time you sent it to trigger a new print. You would set this to 1 if you wanted to print any time it changed or a bigger number if you are getting some jitter on the readings you wanted to suppress.

1 Like

@Grumpy_Mike Thanks for elaborating :smile:

I hope I am not bothering you with my questions, but how should I setup or define lastxPos to hold the last value of xPos I printed ? or what variable should I fill it in with?
because right now it is not defined:

    if( abs( xPos - lastxPos) > 1){
   myPort.write(xPos);
   lastxPos = xPos;
}

i'm assuming you're using processing to control the position using the mouse. that the position is determined by the mouse position. is this correct?

if so, i assume you only want the position to change when the mouse has been moved and a button clicked, but i don't understand how ZZZ related to the robot

@gcjr

I think this video will help you understand more about what I am trying to do. the only differences between my project and his is that I am working with positions instead of angles and with stepper motors instead of servos.
The robot needs ZZZ which changes when the mouse button is pressed to move in the z-axis.

Correct! it is determined by the mouse position (xPos & yPos) and whether the mouse was pressed or not (zPos).

I want (xPos & yPos) to change only when the mouse has been moved OR (zPos) to send only one signal when mouse is pressed.

I wasn't considering this part until you suggested it, I am not sure how to do this yet.

Anyway I think @Grumpy_Mike answer is correct and is the answer I need to solve this problem, but I just need to know how to define/setup lastxPos.

without an event like a mouse button click, the code needs to determine if the mouse has moved.

keep track of the last position, XXXlst and YYYlst and only send an update is (XXX != XXXlst || YYY != YYYlst) or return from draw() when (XXX == XXXlst && YYY == YYYlst), skipping the part that sends an update

1 Like

@gcjr

I was thinking of this but I am not sure how to define XXXlst, which I think my same problem with lastxPos that Grumpy_Mike suggested.
Could you help me with this ?

XXXlst is defined similar to XXX

int XXXlst; 

and it is set to XXX just before XXX is updated

    XXXlst = XXX;
    XXX=round(float((mouseX-300))*2/5);
1 Like

Declare it at the start of the program outside any functions, that makes it global.
Give it a silly value, one that will never be achieved like -9999, the. The first time the code is run it prints the value and the value gets set to a sensible one.

@gcjr
Thanks for your answer :heart: I really appreiciate your help :smile:, it works just fine in the processing IDE. Here is my final code incase someone is interested to see the result:

import processing.serial.*;

Serial myPort;    // The serial port:

int XXX = 0; // x zero
int XXXlst; 
int YYY = 0; // y zero
int YYYlst;
int ZZZ = -180; // z zero (the robot is upsidedown)
int ZZZlst;
int serialBegin = 255;


void setup() {
  size(600,600);

  // open serial port
  //myPort = new Serial(this, Serial.list()[1], 9600);
  myPort = new Serial(this, "COM4", 9600);
  frameRate(100);
  noCursor();
}

void draw() {

  background(255);

  //triangle draw
  triangle(width/2, height, 0, 200, width, 200);

  strokeWeight(3);

  //line draw
  line(300,200,mouseX,mouseY);
  line(150,400,mouseX,mouseY);
  line(450,400,mouseX,mouseY);

  // X and y value are scaled in order to fit the robot space work 
  XXXlst = XXX;
  XXX=round(float((mouseX-300))*2/5);
  YYYlst = YYY;
  YYY=round(float((mouseY-300))*2/5);

  // if mouse is pressed the Z value change
  ZZZlst = ZZZ;
  if (mousePressed && (mouseButton == LEFT)) {
    ZZZ -= 1;
  }
  if (mousePressed && (mouseButton == RIGHT)) {
    ZZZ += 1;
  }

  String xPos;
  String yPos;
  String zPos;


  //write X value in serial port
  xPos="X";
  if(XXX != XXXlst){

  if (XXX > 0) 
    xPos += '+';
  else 
    xPos += '-';
  if (abs(XXX) < 100)
    xPos += '0';
  if (abs(XXX) < 10)
    xPos += '0';
  xPos += abs(XXX);
  }
  
  // write Y value in serial port
  yPos="Y";
  if(YYY != YYYlst){
  
  if (YYY > 0) 
    yPos += '+';
  else 
    yPos += '-';
  if (abs(YYY) < 100)
    yPos += '0';
  if (abs(YYY) < 10)
    yPos += '0';
  yPos += abs(YYY);
  }
  // write Z value in serial port
  zPos="Z";
  if(ZZZ != ZZZlst){
  
    if (ZZZ > 0) 
    zPos += '+';
  else 
    zPos += '-';
  if (abs(ZZZ) < 100)
    zPos += '0';
  if (abs(ZZZ) < 10)
    zPos += '0';
  zPos += abs(ZZZ);
  }
  if(XXX != XXXlst || YYY != YYYlst || ZZZ != ZZZlst ){
  // write x,y,z in the serial port
  myPort.write(xPos);
  myPort.write(yPos);
  myPort.write(yPos);
   // write x,y,z in the monitor
   println(xPos);
   println(yPos);
   println(zPos);
  }

And here are the results printed in the processing IDE: (only changes when the positions change)


Screenshot (681)

Only problem right now lies in my arduino code in Arduino IDE I think, because for some reason I haven't figured out yet my stepper motors stop responding to the Processing IDE. guess I still have more work to do :slight_smile:
Thanks again everyone for helping me in this forum.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.