More encoder MP work

motor-and-encoder
ZodiusInfuser 2022-04-19 20:22:35 +01:00
rodzic 180df9e085
commit 114c83e04e
7 zmienionych plików z 226 dodań i 12 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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())

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);

Wyświetl plik

@ -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");