Renamed Snapshot back to Capture

motor-and-encoder
ZodiusInfuser 2022-04-22 16:06:54 +01:00
rodzic 1bde0acbef
commit ba076ccc7b
6 zmienionych plików z 88 dodań i 86 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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[] = {