Close

Stepper motor driving core. Determining the code efficiency

A project log for Building the Thor robot

Building a 6-axis robot based on the Thor robot. When size DOES matter!

olaf-baeyensOlaf Baeyens 05/12/2017 at 22:500 Comments

For the Thor project I have choose the Ultratronics board v1.0 in combination with DRV8825 Stepper Motor Controller.

According to the specification the stepper pulse must be 1.9 µS high and then 1.9 µS low again to drive one step.

The code I try to use to drive these 7 stepper motors

void MotorExecutionBlock::SendMotorDirectionCommand(byte direction_command) {
	byte level = (direction_command >> 6) & 0x01;
	digitalWrite(X_AXIS_DIRECTION, level);

	level = (direction_command >> 5) & 0x01;
	digitalWrite(Y_AXIS_DIRECTION, level);

	level = (direction_command >> 4) & 0x01;
	digitalWrite(Z_AXIS_DIRECTION, level);

	level = (direction_command >> 3) & 0x01;
	digitalWrite(E0_AXIS_DIRECTION, level);

	level = (direction_command >> 2) & 0x01;
	digitalWrite(E1_AXIS_DIRECTION, level);

	level = (direction_command >> 1) & 0x01;
	digitalWrite(E2_AXIS_DIRECTION, level);

	level = (direction_command >> 0) & 0x01;
	digitalWrite(E3_AXIS_DIRECTION, level);
}
According to the logic analyzer every code line turns out to take 2.24 µS.

7 times 2.24 = 15.7 µS

        byte level = (direction_command >> 6) & 0x01;
	digitalWrite(X_AXIS_DIRECTION, level);

After I have sent all 7 step commands, I intended to wait the desired 2µS delay, but in the above logic analyzer sampling it clearly is takes 23.2 µS

void MotorExecutionBlock::SetMotorStep(byte step_command) {
	// Bit 1 means set the step
	step_command = 0x7F; // 
	SendMotorStepCommand(step_command);
	// wait 2 micro seconds (example below is 1000 micros seconds but for now... 
	MicroDelay(2);

	SendMotorStepCommand(0);
	MicroDelay(2);
}

The Micro delay code is shown. For some reason this code takes 23.2µS

static void MicroDelay(unsigned long delayTime) 
    auto started_waiting_at = micros(); 
    do {
	auto currentTime = micros();
	auto passedTime = (currentTime - started_waiting_at);
	if (passedTime > delayTime) {
         	break;	
        }
    } while (true);
}

Any wait code means that we lose CPU cycles that could have been used for calculations the next phase.

I am thinking about using a simple dummy DigitalWrite command as a way to delay 2µS instead of the micros() method. The step pulse width does not have to be accurate as long as it is > 1.9 µS.

The speed of the stepper motors next pulse are determined by an timer interrupt. And independent of this micro delay.

The total time stuck to this one 7 stepper motor pulse is 36.92 µS when we could have had 2 µS.

Time to improve this code!

To be continued....


Discussions