in reply to [SOLVED] Get element count of CONSTANT list (aref))
For anyone who may be interested, here's the mock-up prototype code I've got so far to turn the stepper motor clockwise (cw()) or counter-clockwise (ccw()). There's a lot of repetitiveness I will be removing, and adding in many more checks etc, but this works quite well thus far:
package Step; use 5.010; use strict; use warnings; use Carp qw(croak); use Data::Dumper; use RPi::Const qw(:all); use WiringPi::API qw(:perl); our $VERSION = '2.3601'; use constant FULL => 2; use constant HALF => 1; use constant NUM_PINS => 0..3; use constant STEPPER_SEQUENCE => [ [qw(1 0 0 1)], [qw(1 0 0 0)], [qw(1 1 0 0)], [qw(0 1 0 0)], [qw(0 1 1 0)], [qw(0 0 1 0)], [qw(0 0 1 1)], [qw(0 0 0 1)], ]; use constant STEP_COUNT => 0+@{ STEPPER_SEQUENCE() }; sub new { my ($class, %args) = @_; my $self = bless {}, $class; if (! exists $args{pins}){ croak "'pins' parameter is required to use this module\n"; } setup_gpio(); $self->_pins($args{pins}); my $delay = $args{delay} // 0.01; $self->delay($delay); my $speed = $args{speed} // 'half'; $self->speed($speed); return $self; } sub cw { my ($self, $degrees) = @_; my $step_counter = 0; my $pins = $self->_pins; for (1..$self->_turns($degrees)){ for my $gpio_pin (NUM_PINS){ if (STEPPER_SEQUENCE->[$step_counter][$gpio_pin]){ write_pin($pins->[$gpio_pin], HIGH); } else { write_pin($pins->[$gpio_pin], LOW); } } $step_counter += $self->_phases; if ($step_counter >= STEP_COUNT){ $step_counter = 0; } $self->_wait; } for (@$pins){ write_pin($_, LOW); pin_mode($_, INPUT); } } sub ccw { my ($self, $degrees) = @_; my $step_counter = 0; my $pins = $self->_pins; for (1..$self->_turns($degrees)){ for my $gpio_pin (NUM_PINS){ if (STEPPER_SEQUENCE->[$step_counter][$gpio_pin]){ write_pin($pins->[$gpio_pin], HIGH); } else { write_pin($pins->[$gpio_pin], LOW); } } $step_counter += $self->_phases * -1; if ($step_counter < 0){ $step_counter = STEP_COUNT + $self->_phases * -1; } $self->_wait; } for (@$pins){ write_pin($_, LOW); pin_mode($_, INPUT); } } sub speed { my ($self, $speed) = @_; if (defined $speed){ if (! grep {$speed ne $_} qw(full half)){ croak "'speed' parameter must be either 'full' or 'half'\n +"; } $self->{speed} = $speed; } return $self->{speed}; } sub delay { my ($self, $delay) = @_; $self->{delay} = $delay if defined $delay; return $self->{delay}; } sub _wait { my ($self) = @_; select(undef, undef, undef, $self->delay); } sub _pins { my ($self, $pins) = @_; if (defined $pins){ if (@$pins != 4){ croak "the 'pins' parameter must include an aref with four + elements\n"; } for (@$pins){ pin_mode($_, OUTPUT); write_pin($_, LOW); } $self->{pins} = $pins; } return $self->{pins}; } sub _phases { return $_[0]->speed eq 'full' ? FULL : HALF; } sub _turns { my ($self, $degrees) = @_; return $self->_phases == 1 ? int($degrees / 5.625 + 0.5) * 64 : int($degrees / 11.25 + 0.5) * 64; } 1;
...and the calling script (the param to ccw() is the degrees in which to turn:
use warnings; use strict; use lib '.'; use Step; my $s = Step->new( pins => [12, 16, 20, 21], speed => 'full' ); #$s->cw(90); $s->ccw(90);
Feedback on any part would be appreciated, particularly with the cw() and ccw() method names. I thought about left() and right(), but perhaps those could be ambiguous in certain scenarios. I do totally like them better. Perhaps they could be aliases with the documentation specifying this?
Update: After some consideration, I think I might alias right(); up() to cw() and left(), down() to ccw(). Thoughts much welcome.
|
|---|