kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Encoder mostly implemented, now with MP support
rodzic
564fecf1de
commit
90fd4b8fb9
|
@ -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;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue