kopia lustrzana https://github.com/pimoroni/pimoroni-pico
More encoder MP work
rodzic
180df9e085
commit
114c83e04e
|
@ -0,0 +1,32 @@
|
|||
import gc
|
||||
import time
|
||||
from encoder import Encoder
|
||||
# from encoder import REVERSED
|
||||
|
||||
"""
|
||||
An example of how to read a mechanical rotary encoder, only when it has turned
|
||||
"""
|
||||
|
||||
# Free up hardware resources ahead of creating a new Encoder
|
||||
gc.collect()
|
||||
|
||||
# Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0
|
||||
PIN_A = 26 # The A channel pin
|
||||
PIN_B = 28 # The B channel pin
|
||||
PIN_C = 27 # The common pin
|
||||
enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C)
|
||||
|
||||
# Uncomment the below line (and the top import) to reverse the counting direction
|
||||
# enc.direction(REVERSED)
|
||||
|
||||
# Loop forever
|
||||
while True:
|
||||
capture = enc.take_snapshot()
|
||||
|
||||
print("Count =", capture.count(), end=", ")
|
||||
print("Angle =", capture.degrees(), end=", ")
|
||||
print("Freq =", capture.frequency(), end=", ")
|
||||
print("Speed =", capture.degrees_per_second())
|
||||
|
||||
time.sleep(0.1)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import gc
|
||||
from encoder import Encoder
|
||||
# from encoder import REVERSED
|
||||
|
||||
"""
|
||||
An example of how to read a mechanical rotary encoder, only when it has turned
|
||||
"""
|
||||
|
||||
# Free up hardware resources ahead of creating a new Encoder
|
||||
gc.collect()
|
||||
|
||||
# Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0
|
||||
PIN_A = 26 # The A channel pin
|
||||
PIN_B = 28 # The B channel pin
|
||||
PIN_C = 27 # The common pin
|
||||
enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C)
|
||||
|
||||
# Uncomment the below line (and the top import) to reverse the counting direction
|
||||
# enc.direction(REVERSED)
|
||||
|
||||
# Print out the initial count, step, and turn (they should all be zero)
|
||||
print("Count =", enc.count(), end=", ")
|
||||
print("Step =", enc.step(), end=", ")
|
||||
print("Turn =", enc.turn())
|
||||
|
||||
# Loop forever
|
||||
while True:
|
||||
if enc.delta() != 0:
|
||||
# Print out the new count, step, and turn
|
||||
print("Count =", enc.count(), end=", ")
|
||||
print("Step =", enc.step(), end=", ")
|
||||
print("Turn =", enc.turn())
|
|
@ -0,0 +1,31 @@
|
|||
import gc
|
||||
import time
|
||||
from encoder import Encoder
|
||||
# from encoder import REVERSED
|
||||
|
||||
"""
|
||||
An example of how to read a mechanical rotary encoder.
|
||||
"""
|
||||
|
||||
# Free up hardware resources ahead of creating a new Encoder
|
||||
gc.collect()
|
||||
|
||||
# Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0
|
||||
PIN_A = 26 # The A channel pin
|
||||
PIN_B = 28 # The B channel pin
|
||||
PIN_C = 27 # The common pin
|
||||
enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C)
|
||||
|
||||
# Uncomment the below line (and the top import) to reverse the counting direction
|
||||
# enc.direction(REVERSED)
|
||||
|
||||
# Loop forever
|
||||
while True:
|
||||
|
||||
# Print out the count, delta, step, and turn
|
||||
print("Count =", enc.count(), end=", ")
|
||||
print("Delta =", enc.delta(), end=", ")
|
||||
print("Step =", enc.step(), end=", ")
|
||||
print("Turn =", enc.turn())
|
||||
|
||||
time.sleep(0.1)
|
|
@ -0,0 +1,40 @@
|
|||
import gc
|
||||
import time
|
||||
from pimoroni import Button
|
||||
from encoder import Encoder
|
||||
# from encoder import REVERSED
|
||||
from motor import motor2040
|
||||
|
||||
"""
|
||||
Demonstrates how to read the counts of multiple motor encoders.
|
||||
|
||||
Press "Boot" to exit the program.
|
||||
"""
|
||||
|
||||
# Free up hardware resources ahead of creating a new Encoder
|
||||
gc.collect()
|
||||
|
||||
# Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0
|
||||
enc_a = Encoder(0, 0, motor2040.ENCODER_A, count_microsteps=True)
|
||||
enc_b = Encoder(0, 1, motor2040.ENCODER_B, count_microsteps=True)
|
||||
enc_c = Encoder(0, 2, motor2040.ENCODER_C, count_microsteps=True)
|
||||
enc_d = Encoder(0, 3, motor2040.ENCODER_D, count_microsteps=True)
|
||||
|
||||
# Uncomment the below line (and the top import) to reverse the counting direction
|
||||
# enc_a.direction(REVERSED)
|
||||
# enc_b.direction(REVERSED)
|
||||
# enc_c.direction(REVERSED)
|
||||
# enc_d.direction(REVERSED)
|
||||
|
||||
# Create the user button
|
||||
user_sw = Button(motor2040.USER_SW)
|
||||
|
||||
# Read the encoders until the user button is pressed
|
||||
while user_sw.raw() is not True:
|
||||
print("A =", enc_a.count(), end=", ")
|
||||
print("B =", enc_b.count(), end=", ")
|
||||
print("C =", enc_c.count(), end=", ")
|
||||
print("D =", enc_d.count())
|
||||
|
||||
time.sleep(0.1)
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import gc
|
||||
import time
|
||||
from pimoroni import Button
|
||||
from encoder import Encoder, MMME_CPR
|
||||
# from encoder import REVERSED
|
||||
from motor import motor2040
|
||||
|
||||
"""
|
||||
Demonstrates how to read the counts of multiple motor encoders.
|
||||
|
||||
Press "Boot" to exit the program.
|
||||
"""
|
||||
|
||||
# Free up hardware resources ahead of creating a new Encoder
|
||||
gc.collect()
|
||||
|
||||
# The gear ratio of the motor the encoder is attached to.
|
||||
GEAR_RATIO = 50
|
||||
CPR = MMME_CPR * GEAR_RATIO
|
||||
|
||||
|
||||
# Create a list of motors
|
||||
ENCODER_PINS = [ motor2040.ENCODER_A, motor2040.ENCODER_B, motor2040.ENCODER_C, motor2040.ENCODER_D ]
|
||||
ENCODER_NAMES = [ "A", "B", "C", "D" ]
|
||||
NUM_ENCODERS = len(ENCODER_PINS)
|
||||
encoders = [Encoder(0, i, ENCODER_PINS[i], counts_per_rev=CPR, count_microsteps=True) for i in range(NUM_ENCODERS)]
|
||||
|
||||
# Uncomment the below line (and the top import) to reverse the counting direction
|
||||
# encoders[0].direction(REVERSED)
|
||||
# encoders[1].direction(REVERSED)
|
||||
# encoders[2].direction(REVERSED)
|
||||
# encoders[3].direction(REVERSED)
|
||||
|
||||
# Create the user button
|
||||
user_sw = Button(motor2040.USER_SW)
|
||||
|
||||
captures = [None] * NUM_ENCODERS
|
||||
|
||||
# Read the encoders until the user button is pressed
|
||||
while user_sw.raw() is not True:
|
||||
# Capture the state of all encoders, at as close to the same moment as possible
|
||||
for i in range(NUM_ENCODERS):
|
||||
captures[i] = encoders[i].take_snapshot()
|
||||
|
||||
# Print out the angle and speed of each encoder
|
||||
for i in range(NUM_ENCODERS):
|
||||
print(ENCODER_NAMES[i], "=", captures[i].degrees(), "|", captures[i].degrees_per_second(), end=", ")
|
||||
|
||||
print()
|
||||
time.sleep(0.1)
|
|
@ -97,6 +97,8 @@ STATIC const mp_map_elem_t encoder_globals_table[] = {
|
|||
|
||||
{ MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(0x00) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_REVERSED), MP_ROM_INT(0x01) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MMME_CPR), MP_ROM_INT(12) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ROTARY_CPR), MP_ROM_INT(24) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_encoder_globals, encoder_globals_table);
|
||||
|
||||
|
|
|
@ -67,32 +67,32 @@ mp_obj_t Snapshot_frequency(mp_obj_t self_in) {
|
|||
|
||||
mp_obj_t Snapshot_revolutions(mp_obj_t self_in) {
|
||||
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
|
||||
return mp_obj_new_int(self->snapshot.revolutions());
|
||||
return mp_obj_new_float(self->snapshot.revolutions());
|
||||
}
|
||||
|
||||
mp_obj_t Snapshot_degrees(mp_obj_t self_in) {
|
||||
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
|
||||
return mp_obj_new_int(self->snapshot.degrees());
|
||||
return mp_obj_new_float(self->snapshot.degrees());
|
||||
}
|
||||
|
||||
mp_obj_t Snapshot_radians(mp_obj_t self_in) {
|
||||
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
|
||||
return mp_obj_new_int(self->snapshot.radians());
|
||||
return mp_obj_new_float(self->snapshot.radians());
|
||||
}
|
||||
|
||||
mp_obj_t Snapshot_revolutions_delta(mp_obj_t self_in) {
|
||||
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
|
||||
return mp_obj_new_int(self->snapshot.revolutions_delta());
|
||||
return mp_obj_new_float(self->snapshot.revolutions_delta());
|
||||
}
|
||||
|
||||
mp_obj_t Snapshot_degrees_delta(mp_obj_t self_in) {
|
||||
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
|
||||
return mp_obj_new_int(self->snapshot.degrees_delta());
|
||||
return mp_obj_new_float(self->snapshot.degrees_delta());
|
||||
}
|
||||
|
||||
mp_obj_t Snapshot_radians_delta(mp_obj_t self_in) {
|
||||
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
|
||||
return mp_obj_new_int(self->snapshot.radians_delta());
|
||||
return mp_obj_new_float(self->snapshot.radians_delta());
|
||||
}
|
||||
|
||||
mp_obj_t Snapshot_revolutions_per_second(mp_obj_t self_in) {
|
||||
|
@ -137,7 +137,11 @@ void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki
|
|||
mp_print_str(print, ", ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(pins.b), PRINT_REPR);
|
||||
mp_print_str(print, ", ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->encoder->common_pin()), PRINT_REPR);
|
||||
uint common_pin = self->encoder->common_pin();
|
||||
if(common_pin == PIN_UNUSED)
|
||||
mp_print_str(print, "PIN_UNUSED");
|
||||
else
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->encoder->common_pin()), PRINT_REPR);
|
||||
mp_print_str(print, ")");
|
||||
|
||||
if(self->encoder->direction() == NORMAL)
|
||||
|
@ -155,12 +159,14 @@ void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki
|
|||
mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_Encoder_obj_t *self = nullptr;
|
||||
|
||||
enum { ARG_pio, ARG_sm, ARG_pins, ARG_common_pin, ARG_count_microsteps, ARG_freq_divider };
|
||||
enum { ARG_pio, ARG_sm, ARG_pins, ARG_common_pin, ARG_direction, ARG_counts_per_rev, ARG_count_microsteps, ARG_freq_divider };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_pio, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_sm, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_common_pin, MP_ARG_INT, {.u_int = PIN_UNUSED} },
|
||||
{ MP_QSTR_direction, MP_ARG_INT, {.u_int = NORMAL} },
|
||||
{ MP_QSTR_counts_per_rev, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_count_microsteps, MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_freq_divider, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
@ -169,8 +175,16 @@ mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
|||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
PIO pio = args[ARG_pio].u_int == 0 ? pio0 : pio1;
|
||||
int pio_int = args[ARG_pio].u_int;
|
||||
if(pio_int < 0 || pio_int > (int)NUM_PIOS) {
|
||||
mp_raise_ValueError("pio out of range. Expected 0 to 1");
|
||||
}
|
||||
PIO pio = pio_int ? pio0 : pio1;
|
||||
|
||||
int sm = args[ARG_sm].u_int;
|
||||
if(sm < 0 || sm > (int)NUM_PIO_STATE_MACHINES) {
|
||||
mp_raise_ValueError("sm out of range. Expected 0 to 3");
|
||||
}
|
||||
|
||||
size_t pin_count = 0;
|
||||
pin_pair pins;
|
||||
|
@ -208,14 +222,27 @@ mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
|||
pins.b = (uint8_t)b;
|
||||
}
|
||||
|
||||
int direction = args[ARG_direction].u_int;
|
||||
if(direction < 0 || direction > 1) {
|
||||
mp_raise_ValueError("direction out of range. Expected NORMAL (0) or REVERSED (1)");
|
||||
}
|
||||
|
||||
float counts_per_rev = Encoder::DEFAULT_COUNTS_PER_REV;
|
||||
if(args[ARG_counts_per_rev].u_obj != mp_const_none) {
|
||||
counts_per_rev = mp_obj_get_float(args[ARG_counts_per_rev].u_obj);
|
||||
if(counts_per_rev < FLT_EPSILON) {
|
||||
mp_raise_ValueError("counts_per_rev out of range. Expected greater than 0.0");
|
||||
}
|
||||
}
|
||||
|
||||
bool count_microsteps = args[ARG_count_microsteps].u_bool;
|
||||
|
||||
float freq_divider = Encoder::DEFAULT_FREQ_DIVIDER;
|
||||
if(args[ARG_freq_divider].u_obj != mp_const_none) {
|
||||
freq_divider = mp_obj_get_float(args[ARG_freq_divider].u_obj);
|
||||
}
|
||||
|
||||
bool count_microsteps = args[ARG_count_microsteps].u_bool;
|
||||
|
||||
Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_common_pin].u_int, NORMAL, Encoder::DEFAULT_COUNTS_PER_REV, count_microsteps, freq_divider);
|
||||
Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_common_pin].u_int, (Direction)direction, counts_per_rev, count_microsteps, freq_divider);
|
||||
if(!encoder->init()) {
|
||||
delete encoder;
|
||||
mp_raise_msg(&mp_type_RuntimeError, "unable to allocate the hardware resources needed to initialise this Encoder. Try running `import gc` followed by `gc.collect()` before creating it");
|
||||
|
|
Ładowanie…
Reference in New Issue