-
Notifications
You must be signed in to change notification settings - Fork 118
Simplify Stepper::stepMotor() #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
edgar-bonet
wants to merge
1
commit into
arduino-libraries:master
Choose a base branch
from
edgar-bonet:simpler
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Instead of separately coding each step, use the fact that all pins follow the same periodic pattern, with phase shifts between them. For the 5-pin steppers, hard-code the pattern in a PROGMEM array, as this is cheaper than reducing a number modulo 10 on chips lacking a hardware divider.
Memory usage change @ 600c2a6
Click for full report table
Click for full report CSV
|
Note that this version of Source code (click to expand/collapse)/*
* test-simpler.c: Test change in branch `simpler'.
*
* Build:
* g++ -O2 -Wall -Wextra test-simpler.cpp -o test-simpler
*/
/***********************************************************************
* Test harness.
*/
#include <cstdint>
#include <cstdio>
#define PROGMEM
#define LOW 0
#define HIGH 1
#define pgm_read_byte(addr) (*(const uint8_t*)(addr))
static uint8_t pin_values[5];
void reset_pins()
{
for (int i = 0; i < 5; i++)
pin_values[i] = 8;
}
void digitalWrite(uint8_t pin, uint8_t value)
{
pin_values[pin] = value ? 1 : 0;
}
void show_pin_states(int count)
{
for (int i = 0; i < count; i++)
printf("%d", pin_values[i]);
}
struct Stepper {
void stepMotor_old(int);
void stepMotor_new(int);
int pin_count;
const int motor_pin_1 = 0;
const int motor_pin_2 = 1;
const int motor_pin_3 = 2;
const int motor_pin_4 = 3;
const int motor_pin_5 = 4;
} stepper;
void test(int pin_count, int phase_count)
{
stepper.pin_count = pin_count;
puts("ph old new");
for (int i = 0; i < phase_count; i++) {
printf("%d ", i);
reset_pins();
stepper.stepMotor_old(i);
show_pin_states(pin_count);
printf(" ");
reset_pins();
stepper.stepMotor_new(i);
show_pin_states(pin_count);
putchar('\n');
}
}
int main()
{
printf("2 pins:\n");
test(2, 4);
printf("\n4 pins:\n");
test(4, 4);
printf("\n5 pins:\n");
test(5, 10);
}
/***********************************************************************
* Original implementation.
*/
#define stepMotor stepMotor_old
void Stepper::stepMotor(int thisStep)
{
if (this->pin_count == 2) {
switch (thisStep) {
case 0: // 01
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
break;
case 1: // 11
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, HIGH);
break;
case 2: // 10
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
break;
case 3: // 00
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, LOW);
break;
}
}
if (this->pin_count == 4) {
switch (thisStep) {
case 0: // 1010
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
break;
case 1: // 0110
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
break;
case 2: //0101
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
break;
case 3: //1001
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
break;
}
}
if (this->pin_count == 5) {
switch (thisStep) {
case 0: // 01101
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
digitalWrite(motor_pin_5, HIGH);
break;
case 1: // 01001
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, LOW);
digitalWrite(motor_pin_5, HIGH);
break;
case 2: // 01011
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
digitalWrite(motor_pin_5, HIGH);
break;
case 3: // 01010
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
digitalWrite(motor_pin_5, LOW);
break;
case 4: // 11010
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
digitalWrite(motor_pin_5, LOW);
break;
case 5: // 10010
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
digitalWrite(motor_pin_5, LOW);
break;
case 6: // 10110
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, HIGH);
digitalWrite(motor_pin_5, LOW);
break;
case 7: // 10100
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
digitalWrite(motor_pin_5, LOW);
break;
case 8: // 10101
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
digitalWrite(motor_pin_5, HIGH);
break;
case 9: // 00101
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
digitalWrite(motor_pin_5, HIGH);
break;
}
}
}
/***********************************************************************
* Updated implementation.
*/
#undef stepMotor
#define stepMotor stepMotor_new
void Stepper::stepMotor(int thisStep)
{
static PROGMEM const uint8_t phases[] = {
LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, HIGH,
LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH
};
switch (pin_count) {
case 2:
digitalWrite(motor_pin_1, (thisStep+1) & 2);
digitalWrite(motor_pin_2, (thisStep+2) & 2);
break;
case 4:
digitalWrite(motor_pin_4, (thisStep+0) & 2);
digitalWrite(motor_pin_2, (thisStep+1) & 2);
digitalWrite(motor_pin_3, (thisStep+2) & 2);
digitalWrite(motor_pin_1, (thisStep+3) & 2);
break;
case 5:
digitalWrite(motor_pin_1, pgm_read_byte(&phases[thisStep+0]));
digitalWrite(motor_pin_4, pgm_read_byte(&phases[thisStep+2]));
digitalWrite(motor_pin_2, pgm_read_byte(&phases[thisStep+4]));
digitalWrite(motor_pin_5, pgm_read_byte(&phases[thisStep+6]));
digitalWrite(motor_pin_3, pgm_read_byte(&phases[thisStep+8]));
break;
}
} The output of this test program is:
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The current version of
Stepper::stepMotor()
uses oneswitch
statement for each possiblepin_count
, with onecase
per step number, for a total of 18 cases. However, on a stepper motor, all pin signals follow the same periodic pattern, differing only by the initial phase, which suggests the signals could be built algorithmically.This pull request exploits this fact in order to simplify the code. It shortens the method
Stepper::stepMotor()
by 99 lines. Building MotorKnob.ino for an Uno shows 314 bytes of flash were saved.Note that, for the 5-pin motors, the pattern is hard-coded in a
PROGMEM
array, although it could be easily generated asThe array method was chosen because, on devices lacking a hardware divider, that modulo operation would be slow. The array only costs 18 bytes of flash, which is small compared to the flash savings achieved.