is it possible to use map() function for values from processing.

Hi I’m trying to turn a stepper motor depending on the value send from processing. X position of the ball from processing moves from 0 - 200.
I’ve done some online references and came up with this code. However the stepper motor doesn’t move a bit, and also how would i stop the motor when there is no input?
#include <Stepper.h>
const int stepsPerRevolution = 64;
Stepper stepperX(stepsPerRevolution, 8, 10, 9, 11);

int currentValue = 0;
int values[] = {0, 0};

const int steps = 64;
int previous, val;


void setup()  {
  Serial.begin(9600);
  stepperX.setSpeed(200);
}


void loop() {
  if (Serial.available()) {
    int incomingValue = Serial.read();

    values[currentValue] = incomingValue;

    currentValue++;
    if (currentValue > 1) {
      currentValue = 0;
    }
  int Xpos = values[0];
  int Ypos = values[1];

  val = map(Xpos, 0,200,0,steps);
  stepperX.step(val - previous);
  previous = val;
  delay(20);

  }

  
}

Thanks in advance.

    int incomingValue = Serial.read();that reads 1 byte. how is the value sent?

  int value1 = Xpos;
  int value2 = Ypos;

  byte out[] = new byte[2];
  out[0] = byte(value1);
  out[1] = byte(value2);
  myPort.write(out);

Thats the part of the processing code. I checked how it received at the ardiuno by displaying it on and LCD. It receives the values correctly

so what do you send? can you explain what the flow will look like so that you can check if the maths you do makes sense?

so the Xpos will increment or decrement depending on which arrow is pressed. Arduino sees it as values from 0-200. The stepper motor goes in the positive direction if the current value is greater than last value. and it will go the negative direction if the current value is less than the previous value.

clarify... are you sending +1 and -1 or are you sending absolute values? what's in Xpos and Ypos? are those the ones between 0-200 ?

what's the second value for? you don't use it...

  val = [color=red]map(Xpos, 0,200,0,steps);[/color]
  stepperX.step([color=red]val - previous[/color]);
  [color=red]previous = val[/color];

what's that supposed to do if Pos is already between 0 and 200 and why do you want to map to 0..64?? why don't you send between 0 and 64 directly then? and what's the val - previous thingy if you have absolute location?

side note, this

    int incomingValue = Serial.read();
    values[currentValue] = incomingValue;
    currentValue++;

could be written just asvalues[currentValue++] = Serial.read();

@J-M-L, yes very true. I've changed that bit of code to look something like this:

 val = Xpos;
  stepperX.step(val - prev);
  prev = val;

I'm just checking with the Xpos first to make sure if it works or not.

Couple of problems: What happens is the stepper motor steps in the positive position and when I stop pressing the button which moves the ball at processing, the stepper motor goes in the negative postion due to the StepperX.step(val-prev);

And also how is it possible to move the position of the motor at the same time. After experimenting for a bit I noticed that only one action takes place and then does the other action.

I can't think with snippets, we don't know what's going on really... can you post both codes and explain what the user do on the processing side and what you would want to see as a behavior on the arduino side?

I did some troubleshooting and I think I have a figured out the problem. Basically the logic behind my program is to move two stepper motor is the X and Y direction depending on the Xpos and Ypos of a ball sent from processing. I included an extra value for the string which returns a value when a key is released. The reason for that is to stop the stepper motors from moving when the key is released.

So to troubleshoot I displayed the values received to Arduino on an LCD.

Xpos =
Ypos =
CH =

After sometime the values get mixed up so for instance CH value might be in the Xpos so on. How could that be fixed?
Also another issue is how to carry out two function at once in Arduino like moving the two motor at the same time.

Here is my processing code, its not finished. Just checking with the Xpos only yet.

int Xpos = 0;
int Ypos = 0;
int sizeX = 800;
int sizeY = 800;
int ch = 0;

import processing.serial.*;

Serial myPort;


void setup() {
  size(sizeX, sizeY);
  noStroke();

  String portName = Serial.list()[2];
  println(Serial.list());
  myPort = new Serial(this, portName, 9600);
}

void draw() {


  background(123);
  ellipse(Xpos, Ypos, 20, 20);
  //println(Xpos);

  int value1 = Xpos;
  int value2 = Ypos;
  int value3 = ch;
  

  byte out[] = new byte[3];
  out[0] = byte(value1);
  out[1] = byte(value2);
  out[2] = byte(value3);
  myPort.write(out);
}
void keyPressed() {
    ch = 1;
  if (key == CODED) {
    if (keyCode == RIGHT) {
      if (Xpos < sizeX) {
        Xpos = Xpos + 2;
        delay(10);
      }
    }
    if (keyCode == LEFT) {
      if (Xpos >0) {
        Xpos = Xpos - 2;
        delay(10);
      }
    }
    if (keyCode == UP) {
      if (Ypos > 0) {
        Ypos = Ypos - 1;
      }
    }
    if (keyCode == DOWN) {
      if (Ypos < sizeY) {
        Ypos = Ypos  +1;
      }
    }
  }
}

void keyReleased() {  
  ch = 0;
}

Here is my Arduino code,it also its not finished.

#include <Stepper.h>
#define steps 660

Stepper stepperX(steps, 8, 10, 9, 11);

int currentValue = 0;
int values[] = {0, 0, 0};

//const int steps = 64;
int prev, val;


void setup()  {
  Serial.begin(9600);
  stepperX.setSpeed(30);



  lcd.begin (20, 4);
  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home (); // go home
}


void loop() {
  if (Serial.available()) {
    int incomingValue = Serial.read();

    values[currentValue] = incomingValue;

    currentValue++;
    if (currentValue > 2) {
      currentValue = 0;
    }

  }
  int Xpos = values[0];
  int Ypos = values[1];
  int ch = values[2];
  val = Xpos; //tried multiplying with a number too so that the motor moves faster, more steps. did work sometimes

if(ch == 1){
  stepperX.step(val - prev);
  prev = val;
}else{
  stepperX.step(0);

}

 lcd.setCursor(0,1);
 lcd.print(Xpos);
 lcd.setCursor(0,2);
 lcd.print(Ypos);
 lcd.setCursor(0,3);
 lcd.print(ch);

}

Any help is greatly appreciated.

How could that be fixed?

Instead of sending binary data, send strings. “<xxxx, yyyy, ch>”.

Use Robin’s method for reading serial data with start and end markers.

@PaulS yes I've already referred to Robin's post, I'm still having some trouble wrapping my head around the functions.

Yami89:
@PaulS yes I've already referred to Robin's post, I'm still having some trouble wrapping my head around the functions.

If you say what you are having trouble understanding I will try to help.

Referring to your title

is it possible to use map() function for values from processing.

Your PC has enormously greater computing power than an Arduino so make all the adjustments in the PC program and send to the Arduino data that it can work with directly - such as the number of steps to take.

...R

Thanks @Robin2,

First of all I couldn't figure out for the life of me on how to write a string from processing here is my processing code for the string.

void draw() {
  background(123);
  ellipse(Xpos, Ypos, 20, 20);
  out[0] = Xpos;
  out[1] = Ypos;
  out[2] = ch;
  myPort.write("out");
  println(out);
}

and from the Arduino end, by referring to your examples I couldn't figure out why I would need use the end markers etc. Basically is there a possibility where Arduino could read and array and I could say which element is which Xpos, Ypos, ch.. and use it from there on. Isn't there a way to read the whole string.

Isn’t there a way to read the whole string.

Yes. Just like you read this reply - one character at a time.

First of all I couldn’t figure out for the life of me on how to write a string from processing

myPort.write("<");
myPort.write(String.valueOf(Xpos));
myPort.write(",");
myPort.write(String.valueOf(Ypos));
myPort.write(",");
myPort.write(String.valueOf(ch));
myPort.write(">");

Yami89:
I couldn't figure out why I would need use the end markers etc.

Without start- and end-markers the Arduino might think that the message starts at what is really the middle of the message.

@PaulS has explained the Processing stuff. I am not familiar with it.

...R

Thanks very much I’m now able to send the exact co-ordinates to Arduino. I used Example 5 from @Robin2 post.

I haven’t tried it with the stepper motors yet. The next problem I anticipate would be to drive the two motors at the same time which is not possible. I came across a post https://forum.arduino.cc/index.php?topic=93706.0 which talks about the same problem.

@PaulS you’ve given a great solution for the problem, but can you help me figure out how can I use it because with my code the motors doesn’t necessarily move together all the time. Would it make sense to have an if statement to see if both motors have to move at the same time and execute the solution you’ve given in the other post?

for(int s=0; s<step_360; s++)
{
 myStepper1.step(1);
 myStepper2.step(1);
}

Yami89:
would be to drive the two motors at the same time which is not possible.

Of course it is.

But you should use the AccelStepper library.

...R

Robin2:
Of course it is.

But you should use the AccelStepper library.

…R

Oh I see, so I have to rethink the whole code right.

Here is the code, which does work but doesn’t move the two motors at once.

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
int Xpos = 0;
int Ypos = 0;
int ch = 0;

boolean newData = false;
int prevX, valX;
int prevY, valY;
#include <Stepper.h>
#define steps 660

Stepper stepperX(steps, 8, 10, 9, 11);
Stepper stepperY(steps, 2, 4, 3, 5);

//============

void setup() {
  Serial.begin(9600);
  stepperX.setSpeed(30);
  stepperY.setSpeed(30);

}

//============

void loop() {
  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    newData = false;
  }

  if (ch == 1) {
    valX = Xpos * 10;
    valY = Ypos * 10;
    if (Xpos > 0) {
      stepperX.step(valX - prevX);
      prevX = valX;
    }
    if (Ypos > 0) {
      stepperY.step(valY - prevY);
      prevY = valY;

    }
  } else {
    stepperX.step(0);
    stepperY.step(0);


  }

}

Here is the code I wrote to make the motors move together. Tried it but it didn’t work :(. But after thinking about it just realised that the way the processing code is written the ball on screen also only moves one axis at a time. I should try a ‘reset’ function where Xpos and Ypos decrements until it comes to the origin - I’ll give it a go. Could you please comment on the code below. Thanks a million :slight_smile:

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
int Xpos = 0;
int Ypos = 0;
int ch = 0;

boolean newData = false;
int prevX, valX;
int prevY, valY;
#include <Stepper.h>
#define steps 660

Stepper stepperX(steps, 8, 10, 9, 11);
Stepper stepperY(steps, 2, 4, 3, 5);



//============

void setup() {
  Serial.begin(9600);
  stepperX.setSpeed(30);
  stepperY.setSpeed(30);

}

//============

void loop() {
  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    newData = false;
  }

  if (ch == 1) {
    valX = Xpos * 10;
    valY = Ypos * 10;

    for (int s = 0; s < steps; s++)
    {
      stepX();
      stepY();
    }






  } else {
    stepperX.step(0);
    stepperY.step(0);
  }

}






void stepX() {
  if (Xpos > 0) {
    stepperX.step(valX - prevX);
    prevX = valX;
  }
}

void stepY() {
  if (Ypos > 0) {
    stepperY.step(valY - prevY);
    prevY = valY;

  }
}

You are not going to get simultaneous movement of two steppers using the standard Stepper library unless you just move the motors one step each at a time.

The AccelStepper library is much more comprehensive.

...R