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 target_sources(${DRIVER_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/encoder.cpp ${CMAKE_CURRENT_LIST_DIR}/encoder.cpp
${CMAKE_CURRENT_LIST_DIR}/capture.cpp
) )
pico_generate_pio_header(${DRIVER_NAME} ${CMAKE_CURRENT_LIST_DIR}/encoder.pio) pico_generate_pio_header(${DRIVER_NAME} ${CMAKE_CURRENT_LIST_DIR}/encoder.pio)

Wyświetl plik

@ -1,4 +1,5 @@
#include <math.h> #include <math.h>
#include <cfloat>
#include <climits> #include <climits>
#include "hardware/irq.h" #include "hardware/irq.h"
#include "encoder.hpp" #include "encoder.hpp"
@ -17,14 +18,63 @@ uint8_t Encoder::claimed_sms[] = { 0x0, 0x0 };
uint Encoder::pio_program_offset[] = { 0, 0 }; uint Encoder::pio_program_offset[] = { 0, 0 };
Encoder::Encoder(PIO pio, uint sm, const pin_pair &pins, uint pin_c, Encoder::Snapshot::Snapshot()
float counts_per_revolution, bool count_microsteps, : count(0), delta(0), frequency(0.0f), counts_per_rev(INT32_MAX) {
uint16_t freq_divider) }
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) : pio(pio)
, sm(sm) , sm(sm)
, enc_pins(pins) , enc_pins(pins)
, pin_c(pin_c) , enc_common_pin(common_pin)
, counts_per_revolution(counts_per_revolution) , enc_direction(direction)
, enc_counts_per_rev(MAX(counts_per_rev, FLT_EPSILON))
, count_microsteps(count_microsteps) , count_microsteps(count_microsteps)
, freq_divider(freq_divider) , freq_divider(freq_divider)
, clocks_per_time((float)(clock_get_hz(clk_sys) / (ENC_LOOP_CYCLES * 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.a, GPIO_FUNC_NULL);
gpio_set_function(enc_pins.b, GPIO_FUNC_NULL); gpio_set_function(enc_pins.b, GPIO_FUNC_NULL);
if(pin_c != PIN_UNUSED) { if(enc_common_pin != PIN_UNUSED) {
gpio_set_function(pin_c, GPIO_FUNC_NULL); 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 // and if there's an associated encoder, have it update its state
for(uint8_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) { for(uint8_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) {
if(encoders[pio_idx][sm] != nullptr) { 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((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 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)) { if((enc_common_pin != PIN_UNUSED) && (enc_common_pin < NUM_BANK0_GPIOS)) {
gpio_init(pin_c); gpio_init(enc_common_pin);
gpio_set_dir(pin_c, GPIO_OUT); gpio_set_dir(enc_common_pin, GPIO_OUT);
gpio_put(pin_c, false); gpio_put(enc_common_pin, false);
} }
pio_sm_claim(pio, sm); 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_fifo_join(&c, PIO_FIFO_JOIN_RX);
sm_config_set_clkdiv_int_frac(&c, freq_divider, 0); 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); pio_sm_init(pio, sm, pio_program_offset[pio_idx], &c);
@ -157,92 +205,97 @@ pin_pair Encoder::pins() const {
return enc_pins; return enc_pins;
} }
uint Encoder::common_pin() const {
return enc_common_pin;
}
bool_pair Encoder::state() const { bool_pair Encoder::state() const {
return bool_pair(enc_state_a, enc_state_b); return bool_pair(enc_state_a, enc_state_b);
} }
int32_t Encoder::count() const { 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 { 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; return revolutions() * 360.0f;
} }
float Encoder::angle_radians() const { float Encoder::radians() const {
return revolutions() * M_TWOPI; return revolutions() * M_TWOPI;
} }
float Encoder::frequency() const { Direction Encoder::direction() const {
return clocks_per_time / (float)time_since; return enc_direction;
} }
float Encoder::revolutions_per_second() const { void Encoder::direction(Direction direction) {
return frequency() / counts_per_revolution; enc_direction = direction;
} }
float Encoder::revolutions_per_minute() const { float Encoder::counts_per_revolution() const {
return revolutions_per_second() * 60.0f; return enc_counts_per_rev;
} }
float Encoder::degrees_per_second() const { void Encoder::counts_per_revolution(float counts_per_rev) {
return revolutions_per_second() * 360.0f; enc_counts_per_rev = MAX(counts_per_rev, FLT_EPSILON);
} }
float Encoder::radians_per_second() const { Encoder::Snapshot Encoder::take_snapshot() {
return revolutions_per_second() * M_TWOPI; // 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() { // Determine the change in counts since the last snapshot was taken
count_offset = enc_count; int32_t change = count - last_snapshot_count;
} last_snapshot_count = 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;
// Calculate the average frequency of state transitions // Calculate the average frequency of state transitions
float average_frequency = 0.0f; float frequency = 0.0f;
if(count_change != 0 && captured_cumulative_time != INT_MAX) { if(change != 0 && cumulative_time != INT32_MAX) {
average_frequency = (clocks_per_time * (float)count_change) / (float)captured_cumulative_time; 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) { void Encoder::process_steps() {
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() {
while(pio->ints1 & (PIO_IRQ1_INTS_SM0_RXNEMPTY_BITS << sm)) { while(pio->ints1 & (PIO_IRQ1_INTS_SM0_RXNEMPTY_BITS << sm)) {
uint32_t received = pio_sm_get(pio, sm); uint32_t received = pio_sm_get(pio, sm);
@ -264,6 +317,8 @@ void Encoder::check_for_transition() {
microstep_time = time_received; microstep_time = time_received;
} }
bool up = (enc_direction == NORMAL);
// Determine what transition occurred // Determine what transition occurred
switch(LAST_STATE(states)) { switch(LAST_STATE(states)) {
//-------------------------------------------------- //--------------------------------------------------
@ -273,14 +328,14 @@ void Encoder::check_for_transition() {
// B _________ // B _________
case MICROSTEP_1: case MICROSTEP_1:
if(count_microsteps) if(count_microsteps)
microstep_up(time_received); microstep(time_received, up);
break; break;
// A _________ // A _________
// B ____|‾‾‾‾ // B ____|‾‾‾‾
case MICROSTEP_3: case MICROSTEP_3:
if(count_microsteps) if(count_microsteps)
microstep_down(time_received); microstep(time_received, !up);
break; break;
} }
break; break;
@ -291,21 +346,21 @@ void Encoder::check_for_transition() {
// A ‾‾‾‾‾‾‾‾‾ // A ‾‾‾‾‾‾‾‾‾
// B ____|‾‾‾‾ // B ____|‾‾‾‾
case MICROSTEP_2: case MICROSTEP_2:
if(count_microsteps || last_travel_dir == CLOCKWISE) if(count_microsteps || step_dir == INCREASING)
microstep_up(time_received); microstep(time_received, up);
last_travel_dir = NO_DIR; // Finished turning clockwise step_dir = NO_DIR; // Finished increasing
break; break;
// A ‾‾‾‾|____ // A ‾‾‾‾|____
// B _________ // B _________
case MICROSTEP_0: case MICROSTEP_0:
if(count_microsteps) if(count_microsteps)
microstep_down(time_received); microstep(time_received, !up);
break; break;
} }
break; break;
//-------------------------------------------------- //--------------------------------------------------
case MICROSTEP_2: case MICROSTEP_2:
switch(CURR_STATE(states)) { switch(CURR_STATE(states)) {
@ -313,18 +368,18 @@ void Encoder::check_for_transition() {
// B ‾‾‾‾‾‾‾‾‾ // B ‾‾‾‾‾‾‾‾‾
case MICROSTEP_3: case MICROSTEP_3:
if(count_microsteps) if(count_microsteps)
microstep_up(time_received); microstep(time_received, up);
last_travel_dir = CLOCKWISE; // Started turning clockwise step_dir = INCREASING; // Started increasing
break; break;
// A ‾‾‾‾‾‾‾‾‾ // A ‾‾‾‾‾‾‾‾‾
// B ‾‾‾‾|____ // B ‾‾‾‾|____
case MICROSTEP_1: case MICROSTEP_1:
if(count_microsteps) if(count_microsteps)
microstep_down(time_received); microstep(time_received, !up);
last_travel_dir = COUNTERCLOCK; // Started turning counter-clockwise step_dir = DECREASING; // Started decreasing
break; break;
} }
break; break;
@ -336,20 +391,43 @@ void Encoder::check_for_transition() {
// B ‾‾‾‾|____ // B ‾‾‾‾|____
case MICROSTEP_0: case MICROSTEP_0:
if(count_microsteps) if(count_microsteps)
microstep_up(time_received); microstep(time_received, up);
break; break;
// A ____|‾‾‾‾ // A ____|‾‾‾‾
// B ‾‾‾‾‾‾‾‾‾ // B ‾‾‾‾‾‾‾‾‾
case MICROSTEP_2: case MICROSTEP_2:
if(count_microsteps || last_travel_dir == COUNTERCLOCK) if(count_microsteps || step_dir == DECREASING)
microstep_down(time_received); microstep(time_received, !up);
last_travel_dir = NO_DIR; // Finished turning counter-clockwise step_dir = NO_DIR; // Finished decreasing
break; break;
} }
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 "hardware/pio.h"
#include "common/pimoroni_common.hpp" #include "common/pimoroni_common.hpp"
#include "capture.hpp" #include "snapshot.hpp"
namespace pimoroni { namespace pimoroni {
enum Direction {
NORMAL = 0,
REVERSED = 1,
};
struct bool_pair { struct bool_pair {
union { union {
bool first; bool first;
@ -26,7 +31,7 @@ namespace pimoroni {
//-------------------------------------------------- //--------------------------------------------------
public: public:
static constexpr float DEFAULT_COUNTS_PER_REV = 24; 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; static const uint16_t DEFAULT_FREQ_DIVIDER = 1;
private: private:
@ -40,20 +45,65 @@ namespace pimoroni {
static const uint32_t TIME_MASK = 0x0fffffff; 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 // Enums
//-------------------------------------------------- //--------------------------------------------------
private: private:
enum Direction { enum StepDir {
NO_DIR = 0, NO_DIR = 0,
CLOCKWISE = 1, INCREASING = 1,
COUNTERCLOCK = -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; PIO pio;
uint sm; uint sm;
pin_pair enc_pins; 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;
const bool count_microsteps = DEFAULT_COUNT_MICROSTEPS; const uint16_t freq_divider;
const uint16_t freq_divider = DEFAULT_FREQ_DIVIDER; const float clocks_per_time;
const float clocks_per_time = 0;
//-------------------------------------------------- //--------------------------------------------------
volatile bool enc_state_a = false; volatile bool enc_state_a = false;
volatile bool enc_state_b = false; volatile bool enc_state_b = false;
volatile int32_t enc_count = 0; volatile int32_t enc_count = 0;
volatile int32_t time_since = 0; volatile int32_t enc_cumulative_time = 0;
volatile Direction last_travel_dir = NO_DIR; volatile int16_t enc_step = 0;
volatile int32_t microstep_time = 0; volatile int16_t enc_turn = 0;
volatile int32_t cumulative_time = 0;
int32_t count_offset = 0; volatile int32_t microstep_time = 0;
int32_t last_captured_count = 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 // Constructors/Destructor
//-------------------------------------------------- //--------------------------------------------------
public: public:
Encoder() {} Encoder(PIO pio, uint sm, const pin_pair &pins, uint common_pin = PIN_UNUSED, Direction direction = NORMAL,
Encoder(PIO pio, uint sm, const pin_pair &pins, uint pin_c = PIN_UNUSED, float counts_per_rev = DEFAULT_COUNTS_PER_REV, bool count_microsteps = DEFAULT_COUNT_MICROSTEPS,
float counts_per_revolution = DEFAULT_COUNTS_PER_REV, bool count_microsteps = DEFAULT_COUNT_MICROSTEPS,
uint16_t freq_divider = DEFAULT_FREQ_DIVIDER); uint16_t freq_divider = DEFAULT_FREQ_DIVIDER);
~Encoder(); ~Encoder();
@ -117,26 +169,34 @@ namespace pimoroni {
// For print access in micropython // For print access in micropython
pin_pair pins() const; pin_pair pins() const;
uint common_pin() const;
bool_pair state() const; bool_pair state() const;
int32_t count() const; int32_t count() const;
int32_t delta();
void zero();
int16_t step() const;
int16_t turn() const;
float revolutions() const; float revolutions() const;
float angle_degrees() const; float degrees() const;
float angle_radians() 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: private:
void microstep_up(int32_t time_since); void process_steps();
void microstep_down(int32_t time_since); void microstep(int32_t time_since, bool up);
void check_for_transition();
}; };
} }

Wyświetl plik

@ -54,7 +54,7 @@ enum DrawState {
uint16_t buffer[PicoExplorer::WIDTH * PicoExplorer::HEIGHT]; uint16_t buffer[PicoExplorer::WIDTH * PicoExplorer::HEIGHT];
PicoExplorer pico_explorer(buffer); 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 encA_readings[READINGS_SIZE];
volatile bool encB_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 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)) { 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 // Take a snapshot of the current encoder state
Capture capture = encoder.perform_capture(); Encoder::Snapshot snapshot = encoder.take_snapshot();
// Spin Motor 1 either clockwise or counterclockwise depending on if B or Y are pressed // 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)) { if(pico_explorer.is_pressed(PicoExplorer::B) && !pico_explorer.is_pressed(PicoExplorer::Y)) {
@ -316,21 +316,21 @@ int main() {
{ {
std::stringstream sstream; 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, 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); pico_explorer.set_pen(255, 128, 255); pico_explorer.text(sstream.str(), Point(110, 150), 200, 3);
} }
{ {
std::stringstream sstream; 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(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); pico_explorer.set_pen(128, 255, 255); pico_explorer.text(sstream.str(), Point(90, 180), 220, 3);
} }
{ {
std::stringstream sstream; 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, 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); 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 *****/ /***** 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___del___obj, Encoder___del__);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_pins_obj, Encoder_pins); 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_state_obj, Encoder_state);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_count_obj, Encoder_count); 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_revolutions_obj, Encoder_revolutions);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_degrees_obj, Encoder_angle_degrees); MP_DEFINE_CONST_FUN_OBJ_1(Encoder_degrees_obj, Encoder_degrees);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_radians_obj, Encoder_angle_radians); MP_DEFINE_CONST_FUN_OBJ_1(Encoder_radians_obj, Encoder_radians);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_frequency_obj, Encoder_frequency); MP_DEFINE_CONST_FUN_OBJ_KW(Encoder_direction_obj, 1, Encoder_direction);
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_second_obj, Encoder_revolutions_per_second); MP_DEFINE_CONST_FUN_OBJ_KW(Encoder_counts_per_revolution_obj, 1, Encoder_counts_per_revolution);
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_take_snapshot_obj, Encoder_take_snapshot); MP_DEFINE_CONST_FUN_OBJ_1(Encoder_take_snapshot_obj, Encoder_take_snapshot);
/***** Binding of Methods *****/ /***** 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[] = { 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___del__), MP_ROM_PTR(&Encoder___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_pins), MP_ROM_PTR(&Encoder_pins_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_state), MP_ROM_PTR(&Encoder_state_obj) },
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&Encoder_count_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_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_degrees), MP_ROM_PTR(&Encoder_degrees_obj) },
{ MP_ROM_QSTR(MP_QSTR_angle_radians), MP_ROM_PTR(&Encoder_angle_radians_obj) }, { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&Encoder_radians_obj) },
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Encoder_frequency_obj) }, { MP_ROM_QSTR(MP_QSTR_direction), MP_ROM_PTR(&Encoder_direction_obj) },
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_second), MP_ROM_PTR(&Encoder_revolutions_per_second_obj) }, { MP_ROM_QSTR(MP_QSTR_counts_per_revolution), MP_ROM_PTR(&Encoder_counts_per_revolution_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_take_snapshot), MP_ROM_PTR(&Encoder_take_snapshot_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); STATIC MP_DEFINE_CONST_DICT(Encoder_locals_dict, Encoder_locals_dict_table);
/***** Class Definition *****/ /***** 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 = { const mp_obj_type_t Encoder_type = {
{ &mp_type_type }, { &mp_type_type },
.name = MP_QSTR_encoder, .name = MP_QSTR_encoder,
@ -50,10 +93,10 @@ const mp_obj_type_t Encoder_type = {
STATIC const mp_map_elem_t encoder_globals_table[] = { 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___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_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_NORMAL), MP_ROM_INT(0x00) },
{ MP_ROM_QSTR(MP_QSTR_LINEAR), MP_ROM_INT(0x01) }, { MP_ROM_QSTR(MP_QSTR_REVERSED), MP_ROM_INT(0x01) },
{ MP_ROM_QSTR(MP_QSTR_CONTINUOUS), MP_ROM_INT(0x02) },
}; };
STATIC MP_DEFINE_CONST_DICT(mp_module_encoder_globals, encoder_globals_table); 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 "drivers/encoder-pio/encoder.hpp"
#include <cstdio> #include <cstdio>
#include <cfloat>
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) #define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
@ -12,6 +12,112 @@ extern "C" {
#include "py/builtin.h" #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 **********/ /********** Encoder **********/
/***** Variables Struct *****/ /***** 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_obj_print_helper(print, mp_obj_new_int(pins.a), PRINT_REPR);
mp_print_str(print, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, mp_obj_new_int(pins.b), PRINT_REPR); mp_obj_print_helper(print, mp_obj_new_int(pins.b), PRINT_REPR);
mp_print_str(print, "), enabled = "); mp_print_str(print, ", ");
/*mp_obj_print_helper(print, self->encoder->is_enabled() ? mp_const_true : mp_const_false, PRINT_REPR); mp_obj_print_helper(print, mp_obj_new_int(self->encoder->common_pin()), PRINT_REPR);
mp_print_str(print, ", pulse = "); mp_print_str(print, ")");
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->pulse()), PRINT_REPR);
mp_print_str(print, ", value = "); if(self->encoder->direction() == NORMAL)
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->value()), PRINT_REPR); mp_print_str(print, ", direction = NORMAL");
mp_print_str(print, ", freq = "); else
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->frequency()), PRINT_REPR); 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, ")"); 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) { 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; _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[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_pio, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_pio, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_sm, 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_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_pin_c, MP_ARG_INT, {.u_int = PIN_UNUSED} }, { MP_QSTR_common_pin, MP_ARG_INT, {.u_int = PIN_UNUSED} },
{ MP_QSTR_calibration, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_count_microsteps, MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_freq, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_freq_divider, MP_ARG_OBJ, {.u_obj = mp_const_none} },
}; };
// Parse args. // 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.a = (uint8_t)a;
pins.b = (uint8_t)b; pins.b = (uint8_t)b;
} }
/*
encoder::Calibration *calib = nullptr; float freq_divider = Encoder::DEFAULT_FREQ_DIVIDER;
encoder::CalibrationType calibration_type = encoder::CalibrationType::ANGULAR; if(args[ARG_freq_divider].u_obj != mp_const_none) {
const mp_obj_t calib_object = args[ARG_calibration].u_obj; freq_divider = mp_obj_get_float(args[ARG_freq_divider].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 = encoder::EncoderState::DEFAULT_FREQUENCY; bool count_microsteps = args[ARG_count_microsteps].u_bool;
if(args[ARG_freq].u_obj != mp_const_none) {
freq = mp_obj_get_float(args[ARG_freq].u_obj);
}
*/
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()) { if(!encoder->init()) {
delete encoder; 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"); 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); 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) { extern mp_obj_t Encoder_state(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
bool_pair state = self->encoder->state(); 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()); 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) { extern mp_obj_t Encoder_revolutions(mp_obj_t self_in) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->revolutions()); 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); _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); _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) { extern mp_obj_t Encoder_direction(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); if(n_args <= 1) {
return mp_obj_new_float(self->encoder->frequency()); 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) { extern mp_obj_t Encoder_counts_per_revolution(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); if(n_args <= 1) {
return mp_obj_new_float(self->encoder->revolutions_per_second()); 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) { // Parse args.
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
return mp_obj_new_float(self->encoder->revolutions_per_minute()); 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(args[ARG_self].u_obj, _Encoder_obj_t);
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
return mp_obj_new_float(self->encoder->degrees_per_second());
}
extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in) { return mp_obj_new_float(self->encoder->counts_per_revolution());
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); }
return mp_obj_new_float(self->encoder->radians_per_second()); 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) { // Parse args.
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
self->encoder->zero_count(); mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
return mp_const_none;
_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) { 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); _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
//Capture capture = self->encoder->perform_capture();
return mp_const_none; // 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" #include "py/runtime.h"
/***** Extern of Class Definition *****/ /***** Extern of Class Definition *****/
extern const mp_obj_type_t Snapshot_type;
extern const mp_obj_type_t Encoder_type; extern const mp_obj_type_t Encoder_type;
/***** Extern of Class Methods *****/ /***** 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 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_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___del__(mp_obj_t self_in);
extern mp_obj_t Encoder_pins(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_state(mp_obj_t self_in);
extern mp_obj_t Encoder_count(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_revolutions(mp_obj_t self_in);
extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in); extern mp_obj_t Encoder_degrees(mp_obj_t self_in);
extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in); extern mp_obj_t Encoder_radians(mp_obj_t self_in);
extern mp_obj_t Encoder_frequency(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_revolutions_per_second(mp_obj_t self_in); 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_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_take_snapshot(mp_obj_t self_in); 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 target_sources(usermod_${MOD_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp ${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 ${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) pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.pio)