Question about Code

I have this code:

StepCount=long(MaxDeltaPos);

time1=micros();
      for (unsigned long n=1; n <= StepCount; n++) 
         { 
             
          for (int a=0; a <=NumberOfAxis; a++)   
          {
           Step[a]= int(n *  StepRatio[a])- int((n - 1) *  StepRatio[a]);
           DoStep +=byte(Step[a]*pow(2,a));

          }
          
        PORTA=DoStep; // slow 2 milli seconds
        PORTA=B11111;   //fast
        PORTA=ZeroPins; //fast
         DoStep=0;
       }
         time2=micros();
         time3=time2-time1;
         Serial.println(time3/StepCount);
}

DoStep is a byte that contains a number from 0 to 255 but runs slow it take 2000 microsteps for each loop. If I coment it out (//PORTA=DoStep; ) then it takes 1 microsecond to run each loop.

Any ideas on what I am doing wrong?

Ok, i'm definitely talking through my hat here but without that dostep statement nothing really changes in that loop. The compiler could just decide you only need to do it once and save you some time.

It's not obvious how many times each loop runs but you could try simplifying the inner loop. I assume your real interest is in speeding this up?

In the inner loop
DoStep=DoStep+Step[a]^a........I think???

The inner loop sets Step[a] to 1 or zero to create a binary number, then I am converting it to a decimal.

I have tried the bitWrite(x, n, b) get a binary number, but PORTA does not work any faster.

Any ideas on what I am doing wrong?

DoStep +=byte(Step[a]*[glow]pow[/glow](2,a));

I believe this is functionally equivalent and much faster…

DoStep +=byte(Step[a] << a);

Looks good...I will try that and see how much time I can save.

OK, I updated my code. It does work faster shifting the bits, but it is still 200 microseconds per loop. Is this as good as it gets or is there more optimization?

StepRatio is a double…I could multiply by 1000 and make it a long???

Anymore ideas?

Thanks Coding Badly…Much better way of doing it!

StepCount=long(MaxDeltaPos);
  time1=micros();
  unsigned int a=0;

  for (unsigned long n=1; n <= StepCount; n++) 
      { 
        for (a=0; a <=NumberOfAxis; a++)   
          {
          Step +=(int(n *  StepRatio[a])- int((n - 1) *  StepRatio[a])) << a; 
          }
        //  Serial.println(Step,BIN);
        PORTA=Step;
        delayMicroseconds(5);
        PORTA=ZeroPins;
        Step=0;
      }
  time2=micros();
  time3=time2-time1;
  Serial.println(time3/MaxDeltaPos);
}

for sure the float will be killing you - get rid of that for starters.

is NumberOfAxis a small number like 2 or 3?

is there anything you can pull out of the inner loop? anything you can make into a constant? look up in a table?

what has changed when you come in here? Is StepRatio always the same? look for things that you can pre-calculate rather than doing it on the fly.

I am wanting to run 6 axis. DualX, Y, Z, A, and B

StepRatio is different for each axis. I am looping to determine if the bit should be 1.

So if X=10 and Y=5, then StepRatioX=1 and StepRatioY=0.5
So X would step twice as much as Y.

I will have to consider the lookup table.

edited to correct Y=5 (was Y=2)

start with the float, that is easy and will make a big difference.

just looking at the code, how come step is zeroed between loops but not before the 1st one? How come the results for the diferent axes are all dropped into PORTA?

If the stepcount thing doesn't have a big range I think you should be looking at a table lookup.

Step is zeroed before just not shown.

I use PORTA to Step the stepper motors, I will use PortB for Direction.

I want them all to move at the same time so I drop them to the port, wait 5us then set the port to zero again

Doesn't seem like a lookup table will work at 5000 steps per inch.

I had an algorithm to step correctly…but I guess it is too slow
This is only 20us, but doesn’t move the steppers correctly

Back to the drawing board

  int Temp[NumberOfAxis]={1,0,0,1,1,0};
  
  time1=micros();
  unsigned int a=0;

  for (unsigned long n=1; n <= StepCount; n++) 
      { 
        for (a=0; a <=NumberOfAxis; a++)   
          {
          Step +=Temp[a] << a; 
          }
       // Serial.println(Step,BIN);
        PORTA=Step;
        delayMicroseconds(5);
        PORTA=ZeroPins;
        Step=B10000000;
      }
  time2=micros();
  time3=time2-time1;
  Serial.println(time3/MaxDeltaPos);
}

Does this one work correctly...
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265772785/6#6

...but too slow?

Yes, works correctly, it puts the right bits to the right pins, but I was hoping for less than 40us per loop.

I changed the StepRatio to a constant int and the loop runs at 20us, but I need to be able to change the pins based on a Ratio.

I tried multiplying to make StepRatio a long, but it did not decrease the loop time.

Lets say StepRatio was 0.3333

when n=1
val=int(n*StepRatio)=0

but if n=4 then then val=1.332

since it is bigger than 1, I need the integer part of this. Is there a fast way of getting the integer part of val?

Lets say StepRatio was 0.3333

when n=1
val=int(n*StepRatio)=0

but if n=4 then then val=1.332

since it is bigger than 1, I need the integer part of this. Is there a fast way of getting the integer part of val?

I think you have to get rid of any floats. I should have realized StepRatio was one.

What if you premultiplied stepratio by some power of 2 - say 256 then get the int by shifting bits off the bottom. So instead of .333 it's 85. 85*4=340, 340>>8 will be the "1" you're looking for without the floats.

It may seem evil but if the above gets you somewhere but not far enought try straightening out that inner loop so you repeat it 6 times and code the stepratios as constants.

Instead of floating-point multiply by 0.33, why not do integer math with divide by 3?

int x = 4;
int val;
val = x/3;  // integer division, result is 1

You'll have to go through a bit of work to convert your step ratios to integer numbers, but if you can eliminate floating-point math you'll get rid of a lot of processing time.

Instead of floating-point multiply by 0.33, why not do integer math with divide by 3?

good thought. In fact, if the ratios were close enough to 1/n you could do the whole step detection with modulo arithmetic. i.e. if stepratio were 1/3 then

((n%3)==1)<<a;
could replace the whole RHS of
Step +=(int(n *  StepRatio[a])- int((n - 1) *  StepRatio[a])) << a;

If the stepratios won’t quite cooperate there must be something there that would work.

A lot of good ideas to try.

The StepRatio can be 1/1000000 or 6754/1032458. It is the percentage of an axis step count to the max axis step count.

I think I can use integers to do this:
Example X=1000 Y=200 Z=42, then
StepRatioX=1000/1000
StepRatioY=200/1000
StepRatioZ=42/1000

Step=+ n*StepRatio-(n-1)*StepRatio would give an interger....right?

I will try these ideas

A lot of good ideas to try.

The StepRatio can be 1/1000000 or 6754/1032458. It is the percentage of an axis step count to the max axis step count.

I think I can use integers to do this:
Example X=1000 Y=200 Z=42, then
StepRatioX=1000/1000
StepRatioY=200/1000
StepRatioZ=42/1000

Step=+ n*StepRatio-(n-1)*StepRatio would give an interger....right?

so they can change each time through? That makes it tougher.

Work on getting rid of the floats. They are your worst issue.