saving a TON of parameters ( integers) for arduino to work with later

hey there community;

I'm interested in arduino for a few month now, so not a complete beginner but also not that advanced with programming.

I'm working on a project wich I already saw a lot of others doing it. you can find it under the names 2-d plotter, polargraph or makelangelo.

short: i want to stepper motors to do some steps go get the pencil to a position. after that i want to give them a new pair of 2 variables (int) to move them to an other position.

my problem :
those steps have to be calculated wich pythagoras ( i need the new lengh of the ropes ), so i calculate the old lenghts and the new ones, the difference are the distance to go wich i can convert to steps.
The thng is moving .. BUT : everytime it hits a checkpoint, it stops and needs quite a bit of time to calculate the new steps to make. i want to get rid of that.
i found out, that square roots etc are making the program slowly.
i cant think of a way to do this without the calculations so i want them all to be calculated at the beginning, so when the steppers finished their first moves, they instantly get the new information where to step next.

is there a way i can pre calculate and save these data? i think we are not talkig about 100 variables, but more of 10.000.
besides arduino IDE i never tried anything else , but i saw someone using a tool, wich seems to do exactly this what i need (pre calculating the movements and then starting the arduino to move).
how does those programmms comunicate ?
how can i write my own programm wich tells the arduino IDE where to move the steppers next?
my guess is, that the computer i'm working with is saving all the data, and gives the new steps to the arduino IDE via serial input?

is somone having experience with this kind of stuff?
or do you even have an idea how to do this plotter smarter and fast enough, that the arduino calculated all that?

thank you a lot, I'm struggeling with this for weeks now.

Yeah, it's called a lookup table. Basically it's an array with all values mapped to their key.

But I really doubt you need that many values even if you do no interpolation whatsoever. So what is the math you want to do?

Another way would be to do all calculations on a PC and just give move commands to the Arduino. But then it's more about parsing serial data and writing a PC application.

septillion:
Yeah, it's called a lookup table. Basically it's an array with all values mapped to their key.

But I really doubt you need that many values even if you do no interpolation whatsoever. So what is the math you want to do?

Another way would be to do all calculations on a PC and just give move commands to the Arduino. But then it's more about parsing serial data and writing a PC application.

thank you so far !

so to be more detailed:

to draw a line on the paper i need to give a lot of 'coordinates' to the motors where they drive to .
if i give them just the start and the ending point it will get to the right position but not in a linear way.
so i want to make the arduino go to 100 points in between my start and ending point, so the line would be better and better linear the more points i give.
the 'coordinates' are converted in length of the two wires on the motor. if i want to go to point x/y , the wire length of the motor 1 would be sqrt(pow(x,2)+ pow(y,2)) , just the pytagoras thing. with motor 2 its nearly the same.
because i need as much points as possible, i need to do this maths a lot of time and my guess is, that this is what is taking so long.

how would i write a tool on my pc to give these calculated lenght (works this via serial input?) to the arduino board wich controles the motors?

Nic0lodeon:
how would i write a tool on my pc to give these calculated lenght (works this via serial input?) to the arduino board wich controles the motors?

Like I said, then you're out of the Arduino help and into whatever language you choose for it :wink: Processing or Python would be the choice of most makers. And something like Polargraph seems to be doing just that.

septillion:
Like I said, then you're out of the Arduino help and into whatever language you choose for it :wink: Processing or Python would be the choice of most makers. And something like Polargraph seems to be doing just that.

i thougth about a second arduino . i dont like the thought to always have a pc turned on for that .
wouldnt it be possible to do all the maths on the first one, and just send the amount of steps for each motor to the second one who turns them ? are wireless connections like the rf 24 fast enough for this kind of thing or would the math just be faster?

Second Arduino is pretty useless. The calculations are indeed the hard part, rest is peanuts. If you don't want a PC you can try a faster and more capable Arduino (compatible board). For example an ESP8266 or ESP32. Both are a lot faster and have hardware support for floating point math and multiplication. Both are done in software on like a Uno.

I'm not sure calculating square roots can produce noticeable slow downs, but I can be wrong, I never did intensive maths calculations with arduino. Maybe the problem is elsewhere ( use of delay() ? ).

And do you know you can compare distances without needing sqrt? For example instead of:

if ( sqrt( (dx*dx) + (dy*dy) ) > d )

you can do:

if ( (dx*dx) + (dy*dy) > d*d )

septillion:
Second Arduino is pretty useless. The calculations are indeed the hard part, rest is peanuts. If you don't want a PC you can try a faster and more capable Arduino (compatible board). For example an ESP8266 or ESP32. Both are a lot faster and have hardware support for floating point math and multiplication. Both are done in software on like a Uno.

thanks for the hint! I'll buy one and try.
but is the second one useless because its still to slow just? i want to make an input controller aswell to control this. can't i set everything up, press start, and the controller already calculates and gives them to the second one, wich waits until like half is done or something?

guix:
I'm not sure calculating square roots can produce noticeable slow downs, but I can be wrong, I never did intensive maths calculations with arduino. Maybe the problem is elsewhere ( use of delay() ? ).

And do you know you can compare distances without needing sqrt? For example instead of:

if ( sqrt( (dx*dx) + (dy*dy) ) > d )

you can do:

if ( (dx*dx) + (dy*dy) > d*d )

i just got rif of delay for the motor driving to try if the calculations can be done while driving the motors but no.

do you have a name for this equations? looks interesting but that does just help me to tell if the last one was bigger, i also need to know the difference between the last an d the current one, and i think, i need to calc the sqrt for each koordinate at least once. can be wrong but i cant come up with a solution to get rid of the sqrt and get the correct difference of distances.

The second one is useles because all the other stuff it needs to do is simple and fast. So a single fast enough controller can just take care of that as well.

Nic0lodeon:
i just got rif of delay for the motor driving to try if the calculations can be done while driving the motors but no.

But YES! Otherwise there is a bug :wink: You want something fast, then NEVER use delay() or block it otherwise. During a delay() NOTHING happens. So it's probably time to rewrite your code after having a look at "Blink without delay"-example and "Several things at the same time"

What guix said is pretty smart indeed. I think the sqrt() is the most heavy calculation (although multiplication is
also not very fast. So if you can eliminate some it will speed it up.

septillion:
The second one is useles because all the other stuff it needs to do is simple and fast. So a single fast enough controller can just take care of that as well.
But YES! Otherwise there is a bug :wink: You want something fast, then NEVER use delay() or block it otherwise. During a delay() NOTHING happens. So it's probably time to rewrite your code after having a look at "Blink without delay"-example and "Several things at the same time"

What guix said is pretty smart indeed. I think the sqrt() is the most heavy calculation (although multiplication is
also not very fast. So if you can eliminate some it will speed it up.

guix commentary is indeed pretty smart. although i lokked it up and you really just compare those two distances.
the explanaition i had, why it wont speed up was : the calculation of the steps to take are two lines, one for motor 1 one for 2, i could place them somewhere else, to but since it is a simple line but pretty long to calc, it wouldnt speed that up.

I would start by optimizing the code you have. Which means (for a start)

  • no delay() anywhere!
  • no String anywhere
  • no Serial.parseX()

if i give them just the start and the ending point it will get to the right position but not in a linear way.

I may have missed, but are these ‘lines’ curved or straight ?
As some have mentioned previously, there are several ways to skin the cat.
Straight lines are easy, curves need to understand what the output is trying to achieve.

Nic0lodeon:
those steps have to be calculated wich pythagoras ( i need the new lengh of the ropes ), so i calculate the old lenghts and the new ones, the difference are the distance to go wich i can convert to steps.
The thng is moving .. BUT : everytime it hits a checkpoint, it stops and needs quite a bit of time to calculate the new steps to make. i want to get rid of that.

What formula, exactly, are you using for the calculation?
Are you doing any other calculations (or anything else) which could be contributing to the slowdown?

What does your (slow) code look like now? Please post your code.

I wonder if this function will be any help:

unsigned int sqrtOfLong(unsigned long x) {
  // inspired by https://www.youtube.com/watch?v=haaCoVrGd6k
  unsigned long leftover     = x;
  unsigned long leftoverStep = 0UL;
  unsigned long result       = 0UL;
  unsigned long resultStep   = 0x40000000UL;
  do {
    leftoverStep >>= 1;    
    result       >>= 1;
    if ((leftoverStep + resultStep) <= leftover) {
      leftoverStep += resultStep;
      leftover     -= leftoverStep;
      result       += resultStep;
      leftoverStep += resultStep;
    }
    resultStep   >>= 2;
  } while (resultStep);
  return ((unsigned int)result);
}

Tests here: http://ideone.com/X6T2qK
and here: http://ideone.com/6oqGfz

Hate to tell you, but calculating square roots, and using Pythagoreus' theorem is completely the WRONG way to do this. You have a start position, as a pair of X,Y coordinates. You have an end position as another pair oof X,Y coordinates. You know how far the X axis moves with each step (or micro-step) of its stepper motor. You know how far the Y axis moves with each step (or micro-step) of its stepper motor. It is trivial to calculate the number of steps each axis must move to get from the start position to the end position. If you need the path to be a straight liner between the two points, it is trivial to calculate how many steps one axis must move for each step of the other axis, which tells you when each needs to be stepped.

NONE of this requires any complex calculation, and, in fact, much of it can be done on-the-fly, using fractional accumulators. This is precisely how it IS done in every CNC machine and nearly every other motion control system on the planet. This is very old technology that is very well understood, and very well documented, so why re-invent the wheel (and badly at that).

Read up on how the MANY public domain CNC controllers, like Grbl, control motion. It can be done very easily, and very precisely, even on a lowly Arduino.

Regards,
Ray L.

If calculation speed is your problem, consider the Wemos D1 Mini. It has a clock speed of 80MHz.

I think he does need it. As far as I read it's not a simple XY driven plotter but a string plotter. Which makes things harder, especially straight lines :wink:

lastchancename:
I may have missed, but are these ‘lines’ curved or straight ?
As some have mentioned previously, there are several ways to skin the cat.
Straight lines are easy, curves need to understand what the output is trying to achieve.

can you describe how you thin that straight lines are easy?
i assume you looked at those machines i try to build.
my machine is going to the right point but it its doing weird curves because the steps for the first motor needs to be aligned to the second motors steps.
example : I’m at the total left side and i want to move it a bit lower. the motor directly above the point has to do less steps then the ne on the right side. If i know just tell them how many steps to go, the end point is correct, but it would not draw a straight line.

odometer:
I wonder if this function will be any help:

unsigned int sqrtOfLong(unsigned long x) {

// inspired by Square root of 2 on the pepper grinder - YouTube
  unsigned long leftover    = x;
  unsigned long leftoverStep = 0UL;
  unsigned long result      = 0UL;
  unsigned long resultStep  = 0x40000000UL;
  do {
    leftoverStep >>= 1;   
    result      >>= 1;
    if ((leftoverStep + resultStep) <= leftover) {
      leftoverStep += resultStep;
      leftover    -= leftoverStep;
      result      += resultStep;
      leftoverStep += resultStep;
    }
    resultStep  >>= 2;
  } while (resultStep);
  return ((unsigned int)result);
}




Tests here: http://ideone.com/X6T2qK
and here: http://ideone.com/6oqGfz

my code is the following right now. its the part wich does the slow down
Can you explain what you example code should do? it looks like we have pretty different ways to do that task

#include <SPI.h>   //nrff KRam
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(8, 9); // CE, CSN
const byte address[6] = "00001";





float stepdist = 0.193125; // mm pro step, bei 15,45 cm pro umdrehung und 800 steps
int fensterbreite = 900;
int fensterhohe= 500 + 200;


int breitesteps = fensterbreite / stepdist;
int hohesteps = fensterhohe / stepdist;
int smoothX = 0;
int smoothY = 0;

int xstart = breitesteps/2.0 ;
int ystart = 200.0 / stepdist;
int xstartm2 = breitesteps-xstart;


  int Abstandm10 = sqrt(pow(xstart, 2)+ pow(ystart,2));
  int Abstandm20 = sqrt(pow(xstartm2,2) + pow(ystart, 2));

void setup() {
  radio.begin();                       //NrF Kram
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();


  
  Serial.begin(9600);
int  xalt = xstart;
int yalt = ystart;

  Serial.println(Abstandm10);
  Serial.println(Abstandm20);
  delay(10000);
}

void loop() {
 int  zeit1 = millis();
 int  xval = analogRead(A0);
 int  yval = analogRead(A1);
yval = map(yval, 0, 1023, 200, 1023); 
smoothX = 0.6 * smoothX + 0.4 * xval;
smoothY = 0.6 * smoothY + 0.4 * yval;

int xvar = smoothX;
int yvar = smoothY;
xvar = map(xvar, 0, 1023, 0, fensterbreite);
yvar = map(yvar, 200, 1023, 200, fensterhohe);
Serial.print("xVal: ");
Serial.print(xvar);
Serial.print("yVal: ");
Serial.println(yvar);

xval = map(xval, 0, 1023, 0, breitesteps);
yval = map(yval, 200, 1023, ystart, hohesteps);

if(digitalRead(7) >= 1)
{
  Serial.println("Button pushed");
int  xziel = xval;
int  yziel = yval;
int  xzielm2 = breitesteps - xziel;
int Abstandm1 = sqrt( pow(xziel, 2) + pow(yziel, 2));
int Abstandm2 = sqrt( pow(xzielm2, 2) + pow(yziel, 2));

  Abstandm1 = Abstandm1 - Abstandm10;
Abstandm2 = Abstandm2 - Abstandm20;
long Abstands[2] = {Abstandm1, Abstandm2};


radio.write(&Abstands, sizeof(Abstands));
radio.write(&Abstands, sizeof(Abstands));

int zeit2 = millis();
int zeitdiff = zeit2- zeit1;
Serial.println(Abstandm1);
Serial.println(Abstandm2);
Serial.print("Zeit in ms : ");
Serial.println(zeitdiff);
delay(2000);
  
}

 
}

I'm still not sure whether you're looking for straight lines or curves, but if you simply want to go from x1,y1 to x2,y2, take a look at Bresenham's algorithm.