kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Renamed Snapshot back to Capture
rodzic
1bde0acbef
commit
ba076ccc7b
|
@ -96,4 +96,18 @@ namespace pimoroni {
|
|||
pin_pair() : first(0), second(0) {}
|
||||
pin_pair(uint8_t first, uint8_t second) : first(first), second(second) {}
|
||||
};
|
||||
|
||||
struct bool_pair {
|
||||
union {
|
||||
bool first;
|
||||
bool a;
|
||||
};
|
||||
union {
|
||||
bool second;
|
||||
bool b;
|
||||
};
|
||||
|
||||
bool_pair() : first(false), second(false) {}
|
||||
bool_pair(bool first, bool second) : first(first), second(second) {}
|
||||
};
|
||||
}
|
|
@ -2,13 +2,14 @@
|
|||
#include <cfloat>
|
||||
#include <climits>
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "encoder.hpp"
|
||||
#include "encoder.pio.h"
|
||||
|
||||
#define LAST_STATE(state) ((state) & 0b0011)
|
||||
#define CURR_STATE(state) (((state) & 0b1100) >> 2)
|
||||
|
||||
namespace pimoroni {
|
||||
namespace encoder {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// STATICS
|
||||
|
@ -18,64 +19,64 @@ uint8_t Encoder::claimed_sms[] = { 0x0, 0x0 };
|
|||
uint Encoder::pio_program_offset[] = { 0, 0 };
|
||||
|
||||
|
||||
Encoder::Snapshot::Snapshot()
|
||||
Encoder::Capture::Capture()
|
||||
: captured_count(0), captured_delta(0), captured_frequency(0.0f), counts_per_rev(INT32_MAX) {
|
||||
}
|
||||
|
||||
Encoder::Snapshot::Snapshot(int32_t count, int32_t delta, float frequency, float counts_per_rev)
|
||||
Encoder::Capture::Capture(int32_t count, int32_t delta, float frequency, float counts_per_rev)
|
||||
: captured_count(count), captured_delta(delta), captured_frequency(frequency)
|
||||
, counts_per_rev(MAX(counts_per_rev, FLT_EPSILON)) { //Clamp counts_per_rev to avoid potential NaN
|
||||
}
|
||||
|
||||
int32_t Encoder::Snapshot::count() const {
|
||||
int32_t Encoder::Capture::count() const {
|
||||
return captured_count;
|
||||
}
|
||||
|
||||
int32_t Encoder::Snapshot::delta() const {
|
||||
int32_t Encoder::Capture::delta() const {
|
||||
return captured_delta;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::frequency() const {
|
||||
float Encoder::Capture::frequency() const {
|
||||
return captured_frequency;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::revolutions() const {
|
||||
float Encoder::Capture::revolutions() const {
|
||||
return (float)captured_count / counts_per_rev;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::degrees() const {
|
||||
float Encoder::Capture::degrees() const {
|
||||
return revolutions() * 360.0f;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::radians() const {
|
||||
float Encoder::Capture::radians() const {
|
||||
return revolutions() * M_TWOPI;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::revolutions_delta() const {
|
||||
float Encoder::Capture::revolutions_delta() const {
|
||||
return (float)captured_delta / counts_per_rev;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::degrees_delta() const {
|
||||
float Encoder::Capture::degrees_delta() const {
|
||||
return revolutions_delta() * 360.0f;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::radians_delta() const {
|
||||
float Encoder::Capture::radians_delta() const {
|
||||
return revolutions_delta() * M_TWOPI;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::revolutions_per_second() const {
|
||||
float Encoder::Capture::revolutions_per_second() const {
|
||||
return captured_frequency / counts_per_rev;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::revolutions_per_minute() const {
|
||||
float Encoder::Capture::revolutions_per_minute() const {
|
||||
return revolutions_per_second() * 60.0f;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::degrees_per_second() const {
|
||||
float Encoder::Capture::degrees_per_second() const {
|
||||
return revolutions_per_second() * 360.0f;
|
||||
}
|
||||
|
||||
float Encoder::Snapshot::radians_per_second() const {
|
||||
float Encoder::Capture::radians_per_second() const {
|
||||
return revolutions_per_second() * M_TWOPI;
|
||||
}
|
||||
|
||||
|
@ -249,7 +250,7 @@ void Encoder::zero() {
|
|||
step_dir = NO_DIR; // may not be wanted?
|
||||
|
||||
last_count = 0;
|
||||
last_snapshot_count = 0;
|
||||
last_capture_count = 0;
|
||||
}
|
||||
|
||||
int16_t Encoder::step() const {
|
||||
|
@ -288,23 +289,23 @@ void Encoder::counts_per_revolution(float counts_per_rev) {
|
|||
enc_counts_per_rev = MAX(counts_per_rev, FLT_EPSILON);
|
||||
}
|
||||
|
||||
Encoder::Snapshot Encoder::take_snapshot() {
|
||||
// Take a snapshot of the current values
|
||||
Encoder::Capture Encoder::capture() {
|
||||
// Take a capture of the current values
|
||||
int32_t count = enc_count;
|
||||
int32_t cumulative_time = enc_cumulative_time;
|
||||
enc_cumulative_time = 0;
|
||||
|
||||
// Determine the change in counts since the last snapshot was taken
|
||||
int32_t change = count - last_snapshot_count;
|
||||
last_snapshot_count = count;
|
||||
// Determine the change in counts since the last capture was taken
|
||||
int32_t change = count - last_capture_count;
|
||||
last_capture_count = count;
|
||||
|
||||
// Calculate the average frequency of state transitions
|
||||
// Calculate the average frequency of steps
|
||||
float frequency = 0.0f;
|
||||
if(change != 0 && cumulative_time != INT32_MAX) {
|
||||
frequency = (clocks_per_time * (float)change) / (float)cumulative_time;
|
||||
}
|
||||
|
||||
return Snapshot(count, change, frequency, enc_counts_per_rev);
|
||||
return Capture(count, change, frequency, enc_counts_per_rev);
|
||||
}
|
||||
|
||||
void Encoder::process_steps() {
|
||||
|
@ -319,8 +320,8 @@ void Encoder::process_steps() {
|
|||
// Extract the time (in cycles) it has been since the last received
|
||||
int32_t time_received = (received & TIME_MASK) + ENC_DEBOUNCE_TIME;
|
||||
|
||||
// For rotary encoders, only every fourth transition is cared about, causing an inaccurate time value
|
||||
// To address this we accumulate the times received and zero it when a transition is counted
|
||||
// For rotary encoders, only every fourth step is cared about, causing an inaccurate time value
|
||||
// To address this we accumulate the times received and zero it when a step is counted
|
||||
if(!count_microsteps) {
|
||||
if(time_received + microstep_time < time_received) // Check to avoid integer overflow
|
||||
time_received = INT32_MAX;
|
||||
|
@ -331,7 +332,7 @@ void Encoder::process_steps() {
|
|||
|
||||
bool up = (enc_direction == NORMAL);
|
||||
|
||||
// Determine what transition occurred
|
||||
// Determine what step occurred
|
||||
switch(LAST_STATE(states)) {
|
||||
//--------------------------------------------------
|
||||
case MICROSTEP_0:
|
||||
|
|
|
@ -3,27 +3,15 @@
|
|||
#include "hardware/pio.h"
|
||||
#include "common/pimoroni_common.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
using namespace pimoroni;
|
||||
|
||||
namespace encoder {
|
||||
|
||||
enum Direction {
|
||||
NORMAL = 0,
|
||||
REVERSED = 1,
|
||||
};
|
||||
|
||||
struct bool_pair {
|
||||
union {
|
||||
bool first;
|
||||
bool a;
|
||||
};
|
||||
union {
|
||||
bool second;
|
||||
bool b;
|
||||
};
|
||||
|
||||
bool_pair() : first(false), second(false) {}
|
||||
bool_pair(bool first, bool second) : first(first), second(second) {}
|
||||
};
|
||||
|
||||
class Encoder {
|
||||
//--------------------------------------------------
|
||||
// Constants
|
||||
|
@ -67,7 +55,7 @@ namespace pimoroni {
|
|||
// Substructures
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
class Snapshot {
|
||||
class Capture {
|
||||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
|
@ -82,8 +70,8 @@ namespace pimoroni {
|
|||
// Constructors
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
Snapshot();
|
||||
Snapshot(int32_t count, int32_t delta, float frequency, float counts_per_rev);
|
||||
Capture();
|
||||
Capture(int32_t count, int32_t delta, float frequency, float counts_per_rev);
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
|
@ -137,7 +125,7 @@ namespace pimoroni {
|
|||
volatile StepDir step_dir = NO_DIR;
|
||||
|
||||
int32_t last_count = 0;
|
||||
int32_t last_snapshot_count = 0;
|
||||
int32_t last_capture_count = 0;
|
||||
|
||||
bool initialised = false;
|
||||
|
||||
|
@ -193,7 +181,7 @@ namespace pimoroni {
|
|||
float counts_per_revolution() const;
|
||||
void counts_per_revolution(float counts_per_rev);
|
||||
|
||||
Snapshot take_snapshot();
|
||||
Capture capture();
|
||||
|
||||
//--------------------------------------------------
|
||||
private:
|
||||
|
|
|
@ -50,13 +50,13 @@ osr_dec:
|
|||
|
||||
; Read the state of both encoder pins and check
|
||||
; if they are different from the last state
|
||||
jmp pin encA_was_high
|
||||
jmp pin enc_a_was_high
|
||||
mov isr, null
|
||||
jmp read_encB
|
||||
encA_was_high:
|
||||
jmp read_enc_b
|
||||
enc_a_was_high:
|
||||
set y, 1
|
||||
mov isr, y
|
||||
read_encB:
|
||||
read_enc_b:
|
||||
in pins, 1
|
||||
mov y, isr
|
||||
jmp x!=y state_changed [1]
|
||||
|
@ -77,7 +77,7 @@ state_changed:
|
|||
|
||||
; Perform a delay to debounce switch inputs
|
||||
set y, (ITERATIONS - 1) [SET_CYCLES - 1]
|
||||
debounce_loop:
|
||||
debounce_loop:
|
||||
jmp y-- debounce_loop [JMP_CYCLES - 1]
|
||||
|
||||
; Initialise the timer, as an inverse, and decrement
|
||||
|
@ -93,8 +93,6 @@ y_dec:
|
|||
; Initialisation Code
|
||||
; --------------------------------------------------
|
||||
% c-sdk {
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
static const uint8_t ENC_LOOP_CYCLES = encoder_wrap - encoder_wrap_target;
|
||||
|
||||
// The time that the debounce takes, as the number of wrap loops that the debounce is equivalent to
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
#include "quadrature_out.pio.h"
|
||||
|
||||
using namespace pimoroni;
|
||||
using namespace encoder;
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Constants
|
||||
//--------------------------------------------------
|
||||
static const pin_pair ENCODER_PINS = {1, 0};
|
||||
static const uint ENCODER_PIN_C = PIN_UNUSED;
|
||||
static const uint ENCODER_SWITCH_PIN = 4;
|
||||
static const pin_pair ENCODER_PINS = {1, 0};
|
||||
static const uint ENCODER_PIN_C = PIN_UNUSED;
|
||||
static const uint ENCODER_SWITCH_PIN = 4;
|
||||
|
||||
static constexpr float COUNTS_PER_REVOLUTION = 24; // 24 is for rotary encoders. For motor magnetic encoders uses
|
||||
// 12 times the gear ratio (e.g. 12 * 20 with a 20:1 ratio motor
|
||||
|
@ -54,7 +55,7 @@ enum DrawState {
|
|||
uint16_t buffer[PicoExplorer::WIDTH * PicoExplorer::HEIGHT];
|
||||
PicoExplorer pico_explorer(buffer);
|
||||
|
||||
Encoder encoder(pio0, 0, ENCODER_PINS, ENCODER_PIN_C, NORMAL, COUNTS_PER_REVOLUTION, COUNT_MICROSTEPS, FREQ_DIVIDER);
|
||||
Encoder enc(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];
|
||||
|
@ -145,13 +146,13 @@ uint32_t draw_plot(Point p1, Point p2, volatile bool (&readings)[READINGS_SIZE],
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool repeating_timer_callback(struct repeating_timer *t) {
|
||||
if(drawing_to_screen && next_scratch_index < SCRATCH_SIZE) {
|
||||
encA_scratch[next_scratch_index] = encoder.state().a;
|
||||
encB_scratch[next_scratch_index] = encoder.state().b;
|
||||
encA_scratch[next_scratch_index] = enc.state().a;
|
||||
encB_scratch[next_scratch_index] = enc.state().b;
|
||||
next_scratch_index++;
|
||||
}
|
||||
else {
|
||||
encA_readings[next_reading_index] = encoder.state().a;
|
||||
encB_readings[next_reading_index] = encoder.state().b;
|
||||
encA_readings[next_reading_index] = enc.state().a;
|
||||
encB_readings[next_reading_index] = enc.state().b;
|
||||
|
||||
next_reading_index++;
|
||||
if(next_reading_index >= READINGS_SIZE)
|
||||
|
@ -179,10 +180,10 @@ void setup() {
|
|||
pico_explorer.clear();
|
||||
pico_explorer.update();
|
||||
|
||||
encoder.init();
|
||||
enc.init();
|
||||
|
||||
bool encA = encoder.state().a;
|
||||
bool encB = encoder.state().b;
|
||||
bool encA = enc.state().a;
|
||||
bool encB = enc.state().b;
|
||||
for(uint i = 0; i < READINGS_SIZE; i++) {
|
||||
encA_readings[i] = encA;
|
||||
encB_readings[i] = encB;
|
||||
|
@ -226,11 +227,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();
|
||||
enc.zero();
|
||||
}
|
||||
|
||||
// Take a snapshot of the current encoder state
|
||||
Encoder::Snapshot snapshot = encoder.take_snapshot();
|
||||
// Capture the encoder state
|
||||
Encoder::Capture capture = enc.capture();
|
||||
|
||||
// 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 +317,21 @@ int main() {
|
|||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << snapshot.count();
|
||||
sstream << capture.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) << snapshot.frequency() << "hz";
|
||||
sstream << std::fixed << std::setprecision(1) << capture.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) << snapshot.revolutions_per_minute();
|
||||
sstream << std::fixed << std::setprecision(1) << capture.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);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
|
||||
|
||||
using namespace pimoroni;
|
||||
//using namespace encoder;
|
||||
using namespace encoder;
|
||||
|
||||
extern "C" {
|
||||
#include "encoder.h"
|
||||
|
@ -304,22 +304,22 @@ extern mp_obj_t Encoder_counts_per_revolution(size_t n_args, const mp_obj_t *pos
|
|||
extern mp_obj_t Encoder_capture(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
|
||||
Encoder::Snapshot snapshot = self->encoder->take_snapshot();
|
||||
Encoder::Capture capture = self->encoder->capture();
|
||||
|
||||
mp_obj_t tuple[] = {
|
||||
mp_obj_new_int(snapshot.count()),
|
||||
mp_obj_new_int(snapshot.delta()),
|
||||
mp_obj_new_float(snapshot.frequency()),
|
||||
mp_obj_new_float(snapshot.revolutions()),
|
||||
mp_obj_new_float(snapshot.degrees()),
|
||||
mp_obj_new_float(snapshot.radians()),
|
||||
mp_obj_new_float(snapshot.revolutions_delta()),
|
||||
mp_obj_new_float(snapshot.degrees_delta()),
|
||||
mp_obj_new_float(snapshot.radians_delta()),
|
||||
mp_obj_new_float(snapshot.revolutions_per_second()),
|
||||
mp_obj_new_float(snapshot.revolutions_per_minute()),
|
||||
mp_obj_new_float(snapshot.degrees_per_second()),
|
||||
mp_obj_new_float(snapshot.radians_per_second()),
|
||||
mp_obj_new_int(capture.count()),
|
||||
mp_obj_new_int(capture.delta()),
|
||||
mp_obj_new_float(capture.frequency()),
|
||||
mp_obj_new_float(capture.revolutions()),
|
||||
mp_obj_new_float(capture.degrees()),
|
||||
mp_obj_new_float(capture.radians()),
|
||||
mp_obj_new_float(capture.revolutions_delta()),
|
||||
mp_obj_new_float(capture.degrees_delta()),
|
||||
mp_obj_new_float(capture.radians_delta()),
|
||||
mp_obj_new_float(capture.revolutions_per_second()),
|
||||
mp_obj_new_float(capture.revolutions_per_minute()),
|
||||
mp_obj_new_float(capture.degrees_per_second()),
|
||||
mp_obj_new_float(capture.radians_per_second()),
|
||||
};
|
||||
|
||||
STATIC const qstr tuple_fields[] = {
|
||||
|
|
Ładowanie…
Reference in New Issue