Encoder mostly implemented, now with MP support

encoder-pio
ZodiusInfuser 2022-04-17 16:16:59 +01:00
rodzic 564fecf1de
commit 90fd4b8fb9
10 zmienionych plików z 595 dodań i 347 usunięć

Wyświetl plik

@ -1,70 +0,0 @@
#include <math.h>
#include <cfloat>
#include "capture.hpp"
namespace pimoroni {
////////////////////////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
////////////////////////////////////////////////////////////////////////////////////////////////////
Capture::Capture(int32_t captured_count, int32_t count_change, float average_frequency, float counts_per_revolution) :
captured_count(captured_count), capture_count_change(count_change), average_frequency(average_frequency),
counts_per_revolution(MAX(counts_per_revolution, FLT_MIN)) { //Clamp counts_per_rev to avoid potential NaN
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// METHODS
////////////////////////////////////////////////////////////////////////////////////////////////////
int32_t Capture::count() const {
return captured_count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::revolutions() const {
return (float)count() / counts_per_revolution;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::angle_degrees() const {
return revolutions() * 360.0f;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::angle_radians() const {
return revolutions() * M_TWOPI;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int32_t Capture::count_change() const {
return capture_count_change;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::frequency() const {
return average_frequency;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::revolutions_per_second() const {
return frequency() / counts_per_revolution;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::revolutions_per_minute() const {
return revolutions_per_second() * 60.0f;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::degrees_per_second() const {
return revolutions_per_second() * 360.0f;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Capture::radians_per_second() const {
return revolutions_per_second() * M_TWOPI;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
}

Wyświetl plik

@ -1,45 +0,0 @@
#pragma once
#include "pico/stdlib.h"
namespace pimoroni {
class Capture {
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
const int32_t captured_count = 0;
const int32_t capture_count_change = 0;
const float average_frequency = 0.0f;
const float counts_per_revolution = 1;
//--------------------------------------------------
// Constructors
//--------------------------------------------------
public:
Capture() {}
Capture(int32_t captured_count, int32_t count_change,
float average_frequency, float counts_per_revolution);
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
int32_t count() const;
float revolutions() const;
float angle_degrees() const;
float angle_radians() const;
int32_t count_change() const;
float frequency() const;
float revolutions_per_second() const;
float revolutions_per_minute() const;
float degrees_per_second() const;
float radians_per_second() const;
};
}

Wyświetl plik

@ -3,7 +3,6 @@ add_library(${DRIVER_NAME} INTERFACE)
target_sources(${DRIVER_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/encoder.cpp
${CMAKE_CURRENT_LIST_DIR}/capture.cpp
)
pico_generate_pio_header(${DRIVER_NAME} ${CMAKE_CURRENT_LIST_DIR}/encoder.pio)

Wyświetl plik

@ -1,4 +1,5 @@
#include <math.h>
#include <cfloat>
#include <climits>
#include "hardware/irq.h"
#include "encoder.hpp"
@ -17,14 +18,63 @@ uint8_t Encoder::claimed_sms[] = { 0x0, 0x0 };
uint Encoder::pio_program_offset[] = { 0, 0 };
Encoder::Encoder(PIO pio, uint sm, const pin_pair &pins, uint pin_c,
float counts_per_revolution, bool count_microsteps,
uint16_t freq_divider)
Encoder::Snapshot::Snapshot()
: count(0), delta(0), frequency(0.0f), counts_per_rev(INT32_MAX) {
}
Encoder::Snapshot::Snapshot(int32_t count, int32_t delta, float frequency, float counts_per_rev)
: count(count), delta(delta), frequency(frequency)
, counts_per_rev(MAX(counts_per_rev, FLT_EPSILON)) { //Clamp counts_per_rev to avoid potential NaN
}
float Encoder::Snapshot::revolutions() const {
return (float)count / counts_per_rev;
}
float Encoder::Snapshot::degrees() const {
return revolutions() * 360.0f;
}
float Encoder::Snapshot::radians() const {
return revolutions() * M_TWOPI;
}
float Encoder::Snapshot::revolutions_delta() const {
return (float)delta / counts_per_rev;
}
float Encoder::Snapshot::degrees_delta() const {
return revolutions_delta() * 360.0f;
}
float Encoder::Snapshot::radians_delta() const {
return revolutions_delta() * M_TWOPI;
}
float Encoder::Snapshot::revolutions_per_second() const {
return frequency / counts_per_rev;
}
float Encoder::Snapshot::revolutions_per_minute() const {
return revolutions_per_second() * 60.0f;
}
float Encoder::Snapshot::degrees_per_second() const {
return revolutions_per_second() * 360.0f;
}
float Encoder::Snapshot::radians_per_second() const {
return revolutions_per_second() * M_TWOPI;
}
Encoder::Encoder(PIO pio, uint sm, const pin_pair &pins, uint common_pin, Direction direction,
float counts_per_rev, bool count_microsteps, uint16_t freq_divider)
: pio(pio)
, sm(sm)
, enc_pins(pins)
, pin_c(pin_c)
, counts_per_revolution(counts_per_revolution)
, enc_common_pin(common_pin)
, enc_direction(direction)
, enc_counts_per_rev(MAX(counts_per_rev, FLT_EPSILON))
, count_microsteps(count_microsteps)
, freq_divider(freq_divider)
, clocks_per_time((float)(clock_get_hz(clk_sys) / (ENC_LOOP_CYCLES * freq_divider))) {
@ -57,8 +107,8 @@ Encoder::~Encoder() {
gpio_set_function(enc_pins.a, GPIO_FUNC_NULL);
gpio_set_function(enc_pins.b, GPIO_FUNC_NULL);
if(pin_c != PIN_UNUSED) {
gpio_set_function(pin_c, GPIO_FUNC_NULL);
if(enc_common_pin != PIN_UNUSED) {
gpio_set_function(enc_common_pin, GPIO_FUNC_NULL);
}
}
}
@ -68,7 +118,7 @@ void Encoder::pio_interrupt_handler(uint pio_idx) {
// and if there's an associated encoder, have it update its state
for(uint8_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) {
if(encoders[pio_idx][sm] != nullptr) {
encoders[pio_idx][sm]->check_for_transition();
encoders[pio_idx][sm]->process_steps();
}
}
}
@ -87,10 +137,10 @@ bool Encoder::init() {
if((enc_pins.a < NUM_BANK0_GPIOS) && (enc_pins.b < NUM_BANK0_GPIOS)) {
// If a Pin C was defined, and valid, set it as a GND to pull the other two pins down
if((pin_c != PIN_UNUSED) && (pin_c < NUM_BANK0_GPIOS)) {
gpio_init(pin_c);
gpio_set_dir(pin_c, GPIO_OUT);
gpio_put(pin_c, false);
if((enc_common_pin != PIN_UNUSED) && (enc_common_pin < NUM_BANK0_GPIOS)) {
gpio_init(enc_common_pin);
gpio_set_dir(enc_common_pin, GPIO_OUT);
gpio_put(enc_common_pin, false);
}
pio_sm_claim(pio, sm);
@ -119,8 +169,6 @@ bool Encoder::init() {
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
sm_config_set_clkdiv_int_frac(&c, freq_divider, 0);
//float div = clock_get_hz(clk_sys) / 500000;
//sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, pio_program_offset[pio_idx], &c);
@ -157,92 +205,97 @@ pin_pair Encoder::pins() const {
return enc_pins;
}
uint Encoder::common_pin() const {
return enc_common_pin;
}
bool_pair Encoder::state() const {
return bool_pair(enc_state_a, enc_state_b);
}
int32_t Encoder::count() const {
return enc_count - count_offset;
return enc_count;
}
int32_t Encoder::delta() {
int32_t count = enc_count; // Store a local copy of enc_count to avoid two reads
// Determine the change in counts since the last time this function was performed
int32_t change = count - last_count;
last_count = count;
return change;
}
void Encoder::zero() {
enc_count = 0;
enc_cumulative_time = 0;
enc_step = 0;
enc_turn = 0;
microstep_time = 0;
step_dir = NO_DIR; // may not be wanted?
last_count = 0;
last_snapshot_count = 0;
}
int16_t Encoder::step() const {
return enc_step;
}
int16_t Encoder::turn() const {
return enc_turn;
}
float Encoder::revolutions() const {
return (float)count() / counts_per_revolution;
return (float)count() / enc_counts_per_rev;
}
float Encoder::angle_degrees() const {
float Encoder::degrees() const {
return revolutions() * 360.0f;
}
float Encoder::angle_radians() const {
float Encoder::radians() const {
return revolutions() * M_TWOPI;
}
float Encoder::frequency() const {
return clocks_per_time / (float)time_since;
Direction Encoder::direction() const {
return enc_direction;
}
float Encoder::revolutions_per_second() const {
return frequency() / counts_per_revolution;
void Encoder::direction(Direction direction) {
enc_direction = direction;
}
float Encoder::revolutions_per_minute() const {
return revolutions_per_second() * 60.0f;
float Encoder::counts_per_revolution() const {
return enc_counts_per_rev;
}
float Encoder::degrees_per_second() const {
return revolutions_per_second() * 360.0f;
void Encoder::counts_per_revolution(float counts_per_rev) {
enc_counts_per_rev = MAX(counts_per_rev, FLT_EPSILON);
}
float Encoder::radians_per_second() const {
return revolutions_per_second() * M_TWOPI;
}
Encoder::Snapshot Encoder::take_snapshot() {
// Take a snapshot of the current values
int32_t count = enc_count;
int32_t cumulative_time = enc_cumulative_time;
enc_cumulative_time = 0;
void Encoder::zero_count() {
count_offset = enc_count;
}
Capture Encoder::perform_capture() {
// Capture the current values
int32_t captured_count = enc_count;
int32_t captured_cumulative_time = cumulative_time;
cumulative_time = 0;
// Determine the change in counts since the last capture was performed
int32_t count_change = captured_count - last_captured_count;
last_captured_count = captured_count;
// Determine the change in counts since the last snapshot was taken
int32_t change = count - last_snapshot_count;
last_snapshot_count = count;
// Calculate the average frequency of state transitions
float average_frequency = 0.0f;
if(count_change != 0 && captured_cumulative_time != INT_MAX) {
average_frequency = (clocks_per_time * (float)count_change) / (float)captured_cumulative_time;
float frequency = 0.0f;
if(change != 0 && cumulative_time != INT32_MAX) {
frequency = (clocks_per_time * (float)change) / (float)cumulative_time;
}
return Capture(captured_count, count_change, average_frequency, counts_per_revolution);
return Snapshot(count, change, frequency, enc_counts_per_rev);
}
void Encoder::microstep_up(int32_t time) {
enc_count++;
time_since = time;
microstep_time = 0;
if(time + cumulative_time < time) //Check to avoid integer overflow
cumulative_time = INT_MAX;
else
cumulative_time += time;
}
void Encoder::microstep_down(int32_t time) {
enc_count--;
time_since = 0 - time;
microstep_time = 0;
if(time + cumulative_time < time) //Check to avoid integer overflow
cumulative_time = INT_MAX;
else
cumulative_time += time;
}
void Encoder::check_for_transition() {
void Encoder::process_steps() {
while(pio->ints1 & (PIO_IRQ1_INTS_SM0_RXNEMPTY_BITS << sm)) {
uint32_t received = pio_sm_get(pio, sm);
@ -264,6 +317,8 @@ void Encoder::check_for_transition() {
microstep_time = time_received;
}
bool up = (enc_direction == NORMAL);
// Determine what transition occurred
switch(LAST_STATE(states)) {
//--------------------------------------------------
@ -273,14 +328,14 @@ void Encoder::check_for_transition() {
// B _________
case MICROSTEP_1:
if(count_microsteps)
microstep_up(time_received);
microstep(time_received, up);
break;
// A _________
// B ____|‾‾‾‾
case MICROSTEP_3:
if(count_microsteps)
microstep_down(time_received);
microstep(time_received, !up);
break;
}
break;
@ -291,21 +346,21 @@ void Encoder::check_for_transition() {
// A ‾‾‾‾‾‾‾‾‾
// B ____|‾‾‾‾
case MICROSTEP_2:
if(count_microsteps || last_travel_dir == CLOCKWISE)
microstep_up(time_received);
if(count_microsteps || step_dir == INCREASING)
microstep(time_received, up);
last_travel_dir = NO_DIR; // Finished turning clockwise
step_dir = NO_DIR; // Finished increasing
break;
// A ‾‾‾‾|____
// B _________
case MICROSTEP_0:
if(count_microsteps)
microstep_down(time_received);
microstep(time_received, !up);
break;
}
break;
//--------------------------------------------------
case MICROSTEP_2:
switch(CURR_STATE(states)) {
@ -313,18 +368,18 @@ void Encoder::check_for_transition() {
// B ‾‾‾‾‾‾‾‾‾
case MICROSTEP_3:
if(count_microsteps)
microstep_up(time_received);
last_travel_dir = CLOCKWISE; // Started turning clockwise
microstep(time_received, up);
step_dir = INCREASING; // Started increasing
break;
// A ‾‾‾‾‾‾‾‾‾
// B ‾‾‾‾|____
case MICROSTEP_1:
if(count_microsteps)
microstep_down(time_received);
last_travel_dir = COUNTERCLOCK; // Started turning counter-clockwise
microstep(time_received, !up);
step_dir = DECREASING; // Started decreasing
break;
}
break;
@ -336,20 +391,43 @@ void Encoder::check_for_transition() {
// B ‾‾‾‾|____
case MICROSTEP_0:
if(count_microsteps)
microstep_up(time_received);
microstep(time_received, up);
break;
// A ____|‾‾‾‾
// B ‾‾‾‾‾‾‾‾‾
case MICROSTEP_2:
if(count_microsteps || last_travel_dir == COUNTERCLOCK)
microstep_down(time_received);
if(count_microsteps || step_dir == DECREASING)
microstep(time_received, !up);
last_travel_dir = NO_DIR; // Finished turning counter-clockwise
step_dir = NO_DIR; // Finished decreasing
break;
}
break;
}
}
}
void Encoder::microstep(int32_t time, bool up) {
if(up) {
enc_count++;
if(++enc_step >= (int16_t)enc_counts_per_rev) {
enc_step -= (int16_t)enc_counts_per_rev;
enc_turn++;
}
}
else {
enc_count--;
if(--enc_step < 0) {
enc_step += (int16_t)enc_counts_per_rev;
enc_turn--;
}
}
microstep_time = 0;
if(time + enc_cumulative_time < time) // Check to avoid integer overflow
enc_cumulative_time = INT32_MAX;
else
enc_cumulative_time += time;
}
}

Wyświetl plik

@ -2,10 +2,15 @@
#include "hardware/pio.h"
#include "common/pimoroni_common.hpp"
#include "capture.hpp"
#include "snapshot.hpp"
namespace pimoroni {
enum Direction {
NORMAL = 0,
REVERSED = 1,
};
struct bool_pair {
union {
bool first;
@ -26,7 +31,7 @@ namespace pimoroni {
//--------------------------------------------------
public:
static constexpr float DEFAULT_COUNTS_PER_REV = 24;
static const uint16_t DEFAULT_COUNT_MICROSTEPS = false;
static const bool DEFAULT_COUNT_MICROSTEPS = false;
static const uint16_t DEFAULT_FREQ_DIVIDER = 1;
private:
@ -40,20 +45,65 @@ namespace pimoroni {
static const uint32_t TIME_MASK = 0x0fffffff;
static const uint8_t MICROSTEP_0 = 0b00;
static const uint8_t MICROSTEP_1 = 0b10;
static const uint8_t MICROSTEP_2 = 0b11;
static const uint8_t MICROSTEP_3 = 0b01;
//--------------------------------------------------
// Enums
//--------------------------------------------------
private:
enum Direction {
NO_DIR = 0,
CLOCKWISE = 1,
COUNTERCLOCK = -1,
enum StepDir {
NO_DIR = 0,
INCREASING = 1,
DECREASING = -1,
};
enum MicroStep : uint8_t {
MICROSTEP_0 = 0b00,
MICROSTEP_1 = 0b10,
MICROSTEP_2 = 0b11,
MICROSTEP_3 = 0b01,
};
//--------------------------------------------------
// Substructures
//--------------------------------------------------
public:
class Snapshot {
//--------------------------------------------------
// Variables
//--------------------------------------------------
public:
const int32_t count;
const int32_t delta;
const float frequency;
private:
float counts_per_rev;
//--------------------------------------------------
// Constructors
//--------------------------------------------------
public:
Snapshot();
Snapshot(int32_t count, int32_t delta, float frequency, float counts_per_rev);
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
float revolutions() const;
float degrees() const;
float radians() const;
float revolutions_delta() const;
float degrees_delta() const;
float radians_delta() const;
float revolutions_per_second() const;
float revolutions_per_minute() const;
float degrees_per_second() const;
float radians_per_second() const;
};
@ -64,27 +114,30 @@ namespace pimoroni {
PIO pio;
uint sm;
pin_pair enc_pins;
uint pin_c;
uint enc_common_pin;
Direction enc_direction;
float enc_counts_per_rev;
const float counts_per_revolution = DEFAULT_COUNTS_PER_REV;
const bool count_microsteps = DEFAULT_COUNT_MICROSTEPS;
const uint16_t freq_divider = DEFAULT_FREQ_DIVIDER;
const float clocks_per_time = 0;
const bool count_microsteps;
const uint16_t freq_divider;
const float clocks_per_time;
//--------------------------------------------------
volatile bool enc_state_a = false;
volatile bool enc_state_b = false;
volatile int32_t enc_count = 0;
volatile int32_t time_since = 0;
volatile Direction last_travel_dir = NO_DIR;
volatile int32_t microstep_time = 0;
volatile int32_t cumulative_time = 0;
volatile bool enc_state_a = false;
volatile bool enc_state_b = false;
volatile int32_t enc_count = 0;
volatile int32_t enc_cumulative_time = 0;
volatile int16_t enc_step = 0;
volatile int16_t enc_turn = 0;
int32_t count_offset = 0;
int32_t last_captured_count = 0;
volatile int32_t microstep_time = 0;
volatile StepDir step_dir = NO_DIR;
bool initialised = false;
int32_t last_count = 0;
int32_t last_snapshot_count = 0;
bool initialised = false;
//--------------------------------------------------
@ -102,9 +155,8 @@ namespace pimoroni {
// Constructors/Destructor
//--------------------------------------------------
public:
Encoder() {}
Encoder(PIO pio, uint sm, const pin_pair &pins, uint pin_c = PIN_UNUSED,
float counts_per_revolution = DEFAULT_COUNTS_PER_REV, bool count_microsteps = DEFAULT_COUNT_MICROSTEPS,
Encoder(PIO pio, uint sm, const pin_pair &pins, uint common_pin = PIN_UNUSED, Direction direction = NORMAL,
float counts_per_rev = DEFAULT_COUNTS_PER_REV, bool count_microsteps = DEFAULT_COUNT_MICROSTEPS,
uint16_t freq_divider = DEFAULT_FREQ_DIVIDER);
~Encoder();
@ -117,26 +169,34 @@ namespace pimoroni {
// For print access in micropython
pin_pair pins() const;
uint common_pin() const;
bool_pair state() const;
int32_t count() const;
int32_t delta();
void zero();
int16_t step() const;
int16_t turn() const;
float revolutions() const;
float angle_degrees() const;
float angle_radians() const;
float degrees() const;
float radians() const;
float frequency() const;
float revolutions_per_second() const;
float revolutions_per_minute() const;
float degrees_per_second() const;
float radians_per_second() const;
void zero_count();
Capture perform_capture(); //TODO rename capture to snapshot
//--------------------------------------------------
Direction direction() const;
void direction(Direction direction);
float counts_per_revolution() const;
void counts_per_revolution(float counts_per_rev);
Snapshot take_snapshot();
//--------------------------------------------------
private:
void microstep_up(int32_t time_since);
void microstep_down(int32_t time_since);
void check_for_transition();
void process_steps();
void microstep(int32_t time_since, bool up);
};
}

Wyświetl plik

@ -54,7 +54,7 @@ enum DrawState {
uint16_t buffer[PicoExplorer::WIDTH * PicoExplorer::HEIGHT];
PicoExplorer pico_explorer(buffer);
Encoder encoder(pio0, 0, ENCODER_PINS, ENCODER_PIN_C, COUNTS_PER_REVOLUTION, COUNT_MICROSTEPS, FREQ_DIVIDER);
Encoder encoder(pio0, 0, ENCODER_PINS, ENCODER_PIN_C, NORMAL, COUNTS_PER_REVOLUTION, COUNT_MICROSTEPS, FREQ_DIVIDER);
volatile bool encA_readings[READINGS_SIZE];
volatile bool encB_readings[READINGS_SIZE];
@ -226,11 +226,11 @@ int main() {
// If the user has wired up their encoder switch, and it is pressed, set the encoder count to zero
if(ENCODER_SWITCH_PIN != PIN_UNUSED && gpio_get(ENCODER_SWITCH_PIN)) {
encoder.zero_count();
encoder.zero();
}
// Take a capture, or snapshot of the current encoder state
Capture capture = encoder.perform_capture();
// Take a snapshot of the current encoder state
Encoder::Snapshot snapshot = encoder.take_snapshot();
// Spin Motor 1 either clockwise or counterclockwise depending on if B or Y are pressed
if(pico_explorer.is_pressed(PicoExplorer::B) && !pico_explorer.is_pressed(PicoExplorer::Y)) {
@ -316,21 +316,21 @@ int main() {
{
std::stringstream sstream;
sstream << capture.count();
sstream << snapshot.count;
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("Count:", Point(10, 150), 200, 3);
pico_explorer.set_pen(255, 128, 255); pico_explorer.text(sstream.str(), Point(110, 150), 200, 3);
}
{
std::stringstream sstream;
sstream << std::fixed << std::setprecision(1) << capture.frequency() << "hz";
sstream << std::fixed << std::setprecision(1) << snapshot.frequency << "hz";
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("Freq: ", Point(10, 180), 220, 3);
pico_explorer.set_pen(128, 255, 255); pico_explorer.text(sstream.str(), Point(90, 180), 220, 3);
}
{
std::stringstream sstream;
sstream << std::fixed << std::setprecision(1) << capture.revolutions_per_minute();
sstream << std::fixed << std::setprecision(1) << snapshot.revolutions_per_minute();
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("RPM: ", Point(10, 210), 220, 3);
pico_explorer.set_pen(255, 255, 128); pico_explorer.text(sstream.str(), Point(80, 210), 220, 3);
}

Wyświetl plik

@ -2,42 +2,85 @@
/***** Methods *****/
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot___del___obj, Snapshot___del__);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_count_obj, Snapshot_count);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_delta_obj, Snapshot_delta);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_frequency_obj, Snapshot_frequency);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_obj, Snapshot_revolutions);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_degrees_obj, Snapshot_degrees);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_radians_obj, Snapshot_radians);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_delta_obj, Snapshot_revolutions_delta);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_degrees_delta_obj, Snapshot_degrees_delta);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_radians_delta_obj, Snapshot_radians_delta);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_per_second_obj, Snapshot_revolutions_per_second);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_per_minute_obj, Snapshot_revolutions_per_minute);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_degrees_per_second_obj, Snapshot_degrees_per_second);
MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_radians_per_second_obj, Snapshot_radians_per_second);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder___del___obj, Encoder___del__);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_pins_obj, Encoder_pins);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_common_pin_obj, Encoder_common_pin);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_state_obj, Encoder_state);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_count_obj, Encoder_count);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_delta_obj, Encoder_delta);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_zero_obj, Encoder_zero);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_step_obj, Encoder_step);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_turn_obj, Encoder_turn);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_obj, Encoder_revolutions);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_degrees_obj, Encoder_angle_degrees);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_radians_obj, Encoder_angle_radians);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_frequency_obj, Encoder_frequency);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_second_obj, Encoder_revolutions_per_second);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_minute_obj, Encoder_revolutions_per_minute);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_degrees_per_second_obj, Encoder_degrees_per_second);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_radians_per_second_obj, Encoder_radians_per_second);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_zero_count_obj, Encoder_zero_count);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_degrees_obj, Encoder_degrees);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_radians_obj, Encoder_radians);
MP_DEFINE_CONST_FUN_OBJ_KW(Encoder_direction_obj, 1, Encoder_direction);
MP_DEFINE_CONST_FUN_OBJ_KW(Encoder_counts_per_revolution_obj, 1, Encoder_counts_per_revolution);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_take_snapshot_obj, Encoder_take_snapshot);
/***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t Snapshot_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Snapshot___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&Snapshot_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_delta), MP_ROM_PTR(&Snapshot_delta_obj) },
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Snapshot_frequency_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions), MP_ROM_PTR(&Snapshot_revolutions_obj) },
{ MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&Snapshot_degrees_obj) },
{ MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&Snapshot_radians_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions_delta), MP_ROM_PTR(&Snapshot_revolutions_delta_obj) },
{ MP_ROM_QSTR(MP_QSTR_degrees_delta), MP_ROM_PTR(&Snapshot_degrees_delta_obj) },
{ MP_ROM_QSTR(MP_QSTR_radians_delta), MP_ROM_PTR(&Snapshot_radians_delta_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_second), MP_ROM_PTR(&Snapshot_revolutions_per_second_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_minute), MP_ROM_PTR(&Snapshot_revolutions_per_minute_obj) },
{ MP_ROM_QSTR(MP_QSTR_degrees_per_second), MP_ROM_PTR(&Snapshot_degrees_per_second_obj) },
{ MP_ROM_QSTR(MP_QSTR_radians_per_second), MP_ROM_PTR(&Snapshot_radians_per_second_obj) },
};
STATIC const mp_rom_map_elem_t Encoder_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Encoder___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_pins), MP_ROM_PTR(&Encoder_pins_obj) },
{ MP_ROM_QSTR(MP_QSTR_common_pin), MP_ROM_PTR(&Encoder_common_pin_obj) },
{ MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&Encoder_state_obj) },
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&Encoder_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_delta), MP_ROM_PTR(&Encoder_delta_obj) },
{ MP_ROM_QSTR(MP_QSTR_zero), MP_ROM_PTR(&Encoder_zero_obj) },
{ MP_ROM_QSTR(MP_QSTR_step), MP_ROM_PTR(&Encoder_step_obj) },
{ MP_ROM_QSTR(MP_QSTR_turn), MP_ROM_PTR(&Encoder_turn_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions), MP_ROM_PTR(&Encoder_revolutions_obj) },
{ MP_ROM_QSTR(MP_QSTR_angle_degrees), MP_ROM_PTR(&Encoder_angle_degrees_obj) },
{ MP_ROM_QSTR(MP_QSTR_angle_radians), MP_ROM_PTR(&Encoder_angle_radians_obj) },
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Encoder_frequency_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_second), MP_ROM_PTR(&Encoder_revolutions_per_second_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_minute), MP_ROM_PTR(&Encoder_revolutions_per_minute_obj) },
{ MP_ROM_QSTR(MP_QSTR_degrees_per_second), MP_ROM_PTR(&Encoder_degrees_per_second_obj) },
{ MP_ROM_QSTR(MP_QSTR_radians_per_second), MP_ROM_PTR(&Encoder_radians_per_second_obj) },
{ MP_ROM_QSTR(MP_QSTR_zero_count), MP_ROM_PTR(&Encoder_zero_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&Encoder_degrees_obj) },
{ MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&Encoder_radians_obj) },
{ MP_ROM_QSTR(MP_QSTR_direction), MP_ROM_PTR(&Encoder_direction_obj) },
{ MP_ROM_QSTR(MP_QSTR_counts_per_revolution), MP_ROM_PTR(&Encoder_counts_per_revolution_obj) },
{ MP_ROM_QSTR(MP_QSTR_take_snapshot), MP_ROM_PTR(&Encoder_take_snapshot_obj) },
};
STATIC MP_DEFINE_CONST_DICT(Snapshot_locals_dict, Snapshot_locals_dict_table);
STATIC MP_DEFINE_CONST_DICT(Encoder_locals_dict, Encoder_locals_dict_table);
/***** Class Definition *****/
const mp_obj_type_t Snapshot_type = {
{ &mp_type_type },
.name = MP_QSTR_snapshot,
.print = Snapshot_print,
.make_new = Snapshot_make_new,
.locals_dict = (mp_obj_dict_t*)&Snapshot_locals_dict,
};
const mp_obj_type_t Encoder_type = {
{ &mp_type_type },
.name = MP_QSTR_encoder,
@ -50,10 +93,10 @@ const mp_obj_type_t Encoder_type = {
STATIC const mp_map_elem_t encoder_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_encoder) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Encoder), (mp_obj_t)&Encoder_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Snapshot), (mp_obj_t)&Snapshot_type },
{ MP_ROM_QSTR(MP_QSTR_ANGULAR), MP_ROM_INT(0x00) },
{ MP_ROM_QSTR(MP_QSTR_LINEAR), MP_ROM_INT(0x01) },
{ MP_ROM_QSTR(MP_QSTR_CONTINUOUS), MP_ROM_INT(0x02) },
{ MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(0x00) },
{ MP_ROM_QSTR(MP_QSTR_REVERSED), MP_ROM_INT(0x01) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_encoder_globals, encoder_globals_table);

Wyświetl plik

@ -1,6 +1,6 @@
#include "drivers/encoder-pio/capture.hpp"
#include "drivers/encoder-pio/encoder.hpp"
#include <cstdio>
#include <cfloat>
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
@ -12,6 +12,112 @@ extern "C" {
#include "py/builtin.h"
/********** Snapshot **********/
/***** Variables Struct *****/
typedef struct _Snapshot_obj_t {
mp_obj_base_t base;
Encoder::Snapshot *snapshot;
} _Snapshot_obj_t;
/***** Print *****/
void Snapshot_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; //Unused input parameter
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
Encoder::Snapshot* snap = self->snapshot;
mp_print_str(print, "Snapshot(count = ");
mp_obj_print_helper(print, mp_obj_new_int(snap->count), PRINT_REPR);
mp_print_str(print, ", delta = ");
mp_obj_print_helper(print, mp_obj_new_int(snap->delta), PRINT_REPR);
mp_print_str(print, ", freq = ");
mp_obj_print_helper(print, mp_obj_new_float(snap->frequency), PRINT_REPR);
mp_print_str(print, ")");
}
/***** Constructor *****/
mp_obj_t Snapshot_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
mp_raise_TypeError("cannot create an instance of Snapshot. They can only be created by calling take_snapshot on an Encoder object");
return mp_const_none;
}
/***** Destructor ******/
mp_obj_t Snapshot___del__(mp_obj_t self_in) {
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
delete self->snapshot;
return mp_const_none;
}
/***** Methods *****/
mp_obj_t Snapshot_count(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->count);
}
mp_obj_t Snapshot_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->delta);
}
mp_obj_t Snapshot_frequency(mp_obj_t self_in) {
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
return mp_obj_new_float(self->snapshot->frequency);
}
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());
}
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());
}
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());
}
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());
}
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());
}
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());
}
mp_obj_t Snapshot_revolutions_per_second(mp_obj_t self_in) {
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
return mp_obj_new_float(self->snapshot->revolutions_per_second());
}
mp_obj_t Snapshot_revolutions_per_minute(mp_obj_t self_in) {
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
return mp_obj_new_float(self->snapshot->revolutions_per_minute());
}
mp_obj_t Snapshot_degrees_per_second(mp_obj_t self_in) {
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
return mp_obj_new_float(self->snapshot->degrees_per_second());
}
mp_obj_t Snapshot_radians_per_second(mp_obj_t self_in) {
_Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t);
return mp_obj_new_float(self->snapshot->radians_per_second());
}
/********** Encoder **********/
/***** Variables Struct *****/
@ -32,15 +138,17 @@ void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki
mp_obj_print_helper(print, mp_obj_new_int(pins.a), PRINT_REPR);
mp_print_str(print, ", ");
mp_obj_print_helper(print, mp_obj_new_int(pins.b), PRINT_REPR);
mp_print_str(print, "), enabled = ");
/*mp_obj_print_helper(print, self->encoder->is_enabled() ? mp_const_true : mp_const_false, PRINT_REPR);
mp_print_str(print, ", pulse = ");
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->pulse()), PRINT_REPR);
mp_print_str(print, ", value = ");
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->value()), PRINT_REPR);
mp_print_str(print, ", freq = ");
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->frequency()), PRINT_REPR);
*/
mp_print_str(print, ", ");
mp_obj_print_helper(print, mp_obj_new_int(self->encoder->common_pin()), PRINT_REPR);
mp_print_str(print, ")");
if(self->encoder->direction() == NORMAL)
mp_print_str(print, ", direction = NORMAL");
else
mp_print_str(print, ", direction = REVERSED");
mp_print_str(print, ", counts_per_rev = ");
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->counts_per_revolution()), PRINT_REPR);
mp_print_str(print, ")");
}
@ -49,14 +157,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_pin_c, ARG_calibration, ARG_freq };
enum { ARG_pio, ARG_sm, ARG_pins, ARG_common_pin, 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_pin_c, MP_ARG_INT, {.u_int = PIN_UNUSED} },
{ MP_QSTR_calibration, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_freq, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_common_pin, MP_ARG_INT, {.u_int = PIN_UNUSED} },
{ MP_QSTR_count_microsteps, MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_freq_divider, MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// Parse args.
@ -101,33 +209,15 @@ mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
pins.a = (uint8_t)a;
pins.b = (uint8_t)b;
}
/*
encoder::Calibration *calib = nullptr;
encoder::CalibrationType calibration_type = encoder::CalibrationType::ANGULAR;
const mp_obj_t calib_object = args[ARG_calibration].u_obj;
if(calib_object != mp_const_none) {
if(mp_obj_is_int(calib_object)) {
int type = mp_obj_get_int(calib_object);
if(type < 0 || type >= 3) {
mp_raise_ValueError("type out of range. Expected ANGULAR (0), LINEAR (1) or CONTINUOUS (2)");
}
calibration_type = (encoder::CalibrationType)type;
}
else if(mp_obj_is_type(calib_object, &Calibration_type)) {
calib = (MP_OBJ_TO_PTR2(calib_object, _Calibration_obj_t)->calibration);
}
else {
mp_raise_TypeError("cannot convert object to an integer or a Calibration class instance");
}
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);
}
float freq = encoder::EncoderState::DEFAULT_FREQUENCY;
if(args[ARG_freq].u_obj != mp_const_none) {
freq = mp_obj_get_float(args[ARG_freq].u_obj);
}
*/
bool count_microsteps = args[ARG_count_microsteps].u_bool;
Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_pin_c].u_int);
Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_common_pin].u_int, NORMAL, Encoder::DEFAULT_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");
@ -160,6 +250,12 @@ extern mp_obj_t Encoder_pins(mp_obj_t self_in) {
return mp_obj_new_tuple(2, tuple);
}
extern mp_obj_t Encoder_common_pin(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_int(self->encoder->common_pin());
}
extern mp_obj_t Encoder_state(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
bool_pair state = self->encoder->state();
@ -175,55 +271,124 @@ extern mp_obj_t Encoder_count(mp_obj_t self_in) {
return mp_obj_new_int(self->encoder->count());
}
extern mp_obj_t Encoder_delta(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_int(self->encoder->delta());
}
extern mp_obj_t Encoder_zero(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
self->encoder->zero();
return mp_const_none;
}
extern mp_obj_t Encoder_step(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_int(self->encoder->step());
}
extern mp_obj_t Encoder_turn(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_int(self->encoder->turn());
}
extern mp_obj_t Encoder_revolutions(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->revolutions());
}
extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in) {
extern mp_obj_t Encoder_degrees(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->angle_degrees());
return mp_obj_new_float(self->encoder->degrees());
}
extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in) {
extern mp_obj_t Encoder_radians(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->angle_radians());
return mp_obj_new_float(self->encoder->radians());
}
extern mp_obj_t Encoder_frequency(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->frequency());
extern mp_obj_t Encoder_direction(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
if(n_args <= 1) {
enum { ARG_self };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
};
// Parse args.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t);
return mp_obj_new_int(self->encoder->direction());
}
else {
enum { ARG_self, ARG_direction };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_direction, MP_ARG_REQUIRED | MP_ARG_INT },
};
// Parse args.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t);
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)");
}
self->encoder->direction((Direction)direction);
return mp_const_none;
}
}
extern mp_obj_t Encoder_revolutions_per_second(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->revolutions_per_second());
}
extern mp_obj_t Encoder_counts_per_revolution(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
if(n_args <= 1) {
enum { ARG_self };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
};
extern mp_obj_t Encoder_revolutions_per_minute(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->revolutions_per_minute());
}
// Parse args.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
extern mp_obj_t Encoder_degrees_per_second(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->degrees_per_second());
}
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t);
extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->radians_per_second());
}
return mp_obj_new_float(self->encoder->counts_per_revolution());
}
else {
enum { ARG_self, ARG_counts_per_rev };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_counts_per_rev, MP_ARG_REQUIRED | MP_ARG_OBJ },
};
extern mp_obj_t Encoder_zero_count(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
self->encoder->zero_count();
return mp_const_none;
// Parse args.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t);
float 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");
}
self->encoder->counts_per_revolution(counts_per_rev);
return mp_const_none;
}
}
extern mp_obj_t Encoder_take_snapshot(mp_obj_t self_in) {
//_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
//Capture capture = self->encoder->perform_capture();
return mp_const_none;
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
// Create a new MP Snapshot instance and assign a copy of the encoder's snapshot to it
_Snapshot_obj_t *snap = m_new_obj_with_finaliser(_Snapshot_obj_t);
snap->base.type = &Snapshot_type;
snap->snapshot = new Encoder::Snapshot(self->encoder->take_snapshot());
return MP_OBJ_FROM_PTR(snap);
}
}

Wyświetl plik

@ -2,22 +2,41 @@
#include "py/runtime.h"
/***** Extern of Class Definition *****/
extern const mp_obj_type_t Snapshot_type;
extern const mp_obj_type_t Encoder_type;
/***** Extern of Class Methods *****/
extern void Snapshot_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
extern mp_obj_t Snapshot_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
extern mp_obj_t Snapshot___del__(mp_obj_t self_in);
extern mp_obj_t Snapshot_count(mp_obj_t self_in);
extern mp_obj_t Snapshot_delta(mp_obj_t self_in);
extern mp_obj_t Snapshot_frequency(mp_obj_t self_in);
extern mp_obj_t Snapshot_revolutions(mp_obj_t self_in);
extern mp_obj_t Snapshot_degrees(mp_obj_t self_in);
extern mp_obj_t Snapshot_radians(mp_obj_t self_in);
extern mp_obj_t Snapshot_revolutions_delta(mp_obj_t self_in);
extern mp_obj_t Snapshot_degrees_delta(mp_obj_t self_in);
extern mp_obj_t Snapshot_radians_delta(mp_obj_t self_in);
extern mp_obj_t Snapshot_revolutions_per_second(mp_obj_t self_in);
extern mp_obj_t Snapshot_revolutions_per_minute(mp_obj_t self_in);
extern mp_obj_t Snapshot_degrees_per_second(mp_obj_t self_in);
extern mp_obj_t Snapshot_radians_per_second(mp_obj_t self_in);
extern void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
extern 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);
extern mp_obj_t Encoder___del__(mp_obj_t self_in);
extern mp_obj_t Encoder_pins(mp_obj_t self_in);
extern mp_obj_t Encoder_common_pin(mp_obj_t self_in);
extern mp_obj_t Encoder_state(mp_obj_t self_in);
extern mp_obj_t Encoder_count(mp_obj_t self_in);
extern mp_obj_t Encoder_delta(mp_obj_t self_in);
extern mp_obj_t Encoder_zero(mp_obj_t self_in);
extern mp_obj_t Encoder_step(mp_obj_t self_in);
extern mp_obj_t Encoder_turn(mp_obj_t self_in);
extern mp_obj_t Encoder_revolutions(mp_obj_t self_in);
extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in);
extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in);
extern mp_obj_t Encoder_frequency(mp_obj_t self_in);
extern mp_obj_t Encoder_revolutions_per_second(mp_obj_t self_in);
extern mp_obj_t Encoder_revolutions_per_minute(mp_obj_t self_in);
extern mp_obj_t Encoder_degrees_per_second(mp_obj_t self_in);
extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in);
extern mp_obj_t Encoder_zero_count(mp_obj_t self_in);
extern mp_obj_t Encoder_degrees(mp_obj_t self_in);
extern mp_obj_t Encoder_radians(mp_obj_t self_in);
extern mp_obj_t Encoder_direction(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t Encoder_counts_per_revolution(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t Encoder_take_snapshot(mp_obj_t self_in);

Wyświetl plik

@ -5,7 +5,6 @@ add_library(usermod_${MOD_NAME} INTERFACE)
target_sources(usermod_${MOD_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/capture.cpp
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.cpp
)
pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.pio)