0

I would like to rotate the coordinate system of an Arduino Joystick controller I purchased. The plane covers an area of 1024x1024 units and I would like redefine dynamically the orientation of the device.

This is what I've done so far:

void loop() {

  int x = analogRead(X_pin);
  int y = analogRead(Y_pin);
  int center = 512;

  float *transformed;
  transformed = rotate(
    float(x), float(y), 
    float(center), float(center) 
    PI/2.0
  );

  int tx = int(*transformed);
  int ty = int(*(transformed+1));

  Serial.print(tx);
  Serial.print(",");
  Serial.print(ty);
}

float *rotate(float x, float y, float cx, float cy, float angle) {
  float out[] = {
    cx + (x - cx) * cos(angle) - (y - cy) * sin(angle),
    cy + (x - cx) * sin(angle) + (y - cy) * cos(angle)
  };
  return out;
}

Unfortunately all I'm getting is 0,0.
Is there something wrong with the way I'm using pointers ?

  • Yes, there is something wrong. `return out;` returns a pointer to the first element of array `out`, but `out` ceases to exist after the function returns, so the pointer becomes invalid. – Ian Abbott Sep 09 '19 at 09:29
  • Unrelated to your question, how do you get this running within any form of real-time on Arduino? It doesn't have a FPU and you force it to do double precision floating point (and store the result in single-precision anyway). And also did you consider the actual calling convention in the ABI for passing all those floats around... passing 4x32 bit is going to be a mess. – Lundin Sep 09 '19 at 12:56

2 Answers2

0

return out - in this line, you're returning a local array from rotate. It has automatic storage duration and ceases to exist after rotate returns, and so by attempting to access it in loop you invoke undefined behavior.

Instead, pass an array to be populated as an argument to rotate:

float transformed[2];
rotate(
  float(x), float(y), 
  float(center), float(center) 
  PI/2.0, transformed
);
...
void rotate(float x, float y, float cx, float cy, float angle, float* out) {
  out[0]=cx + (x - cx) * cos(angle) - (y - cy) * sin(angle);
  out[1]=cy + (x - cx) * sin(angle) + (y - cy) * cos(angle);
}

Because transformed is allocated inside loop, it's still available to you after the call to rotate.

user4520
  • 3,401
  • 1
  • 27
  • 50
-1
void loop() {

  int x = analogRead(X_pin);
  int y = analogRead(Y_pin);
  int center = 512;

  float *transformed;
  transformed = rotate(
    float(x), float(y), 
    float(center), float(center) 
    PI/2.0
  );

  int tx = int(*transformed);
  int ty = int(*(transformed+1));

  Serial.print(tx);
  Serial.print(",");
  Serial.print(ty);
}

float *rotate(float x, float y, float cx, float cy, float angle) {
  float out[] = {
    cx + (x - cx) * cos(angle) - (y - cy) * sin(angle),
    cy + (x - cx) * sin(angle) + (y - cy) * cos(angle)
  };
  return out;//you return a local pointer so make memory problem
}

I suggest like below using global variable

float out[2];//this declare before loop() and setup()

void loop() {

  int x = analogRead(X_pin);
  int y = analogRead(Y_pin);
  int center = 512;

  rotate(
    float(x), float(y), 
    float(center), float(center) 
    PI/2.0
  );

  int tx = int(out[0]);
  int ty = int(out[1]);

  Serial.print(tx);
  Serial.print(",");
  Serial.print(ty);
}

void rotate(float x, float y, float cx, float cy, float angle) {
  out[0]=cx + (x - cx) * cos(angle) - (y - cy) * sin(angle);
  out[1]=cy + (x - cx) * sin(angle) + (y - cy) * cos(angle);
}
J CHEN
  • 494
  • 3
  • 9