Skip to content

Commit

Permalink
Merge pull request #171 from cogip/170-motion-control-add-c++-encoder…
Browse files Browse the repository at this point in the history
…-class

170 motion control add c++ encoder class
  • Loading branch information
mlecriva authored Nov 8, 2024
2 parents a745415 + 33b4dd4 commit 92f42ef
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/encoder/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base
2 changes: 2 additions & 0 deletions lib/encoder/Makefile.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Board features required
FEATURES_REQUIRED += periph_qdec
2 changes: 2 additions & 0 deletions lib/encoder/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
USEMODULE_INCLUDES_encoder := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_encoder)
71 changes: 71 additions & 0 deletions lib/encoder/include/encoder/EncoderInterface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include <cstdint>

#include "etl/math_constants.h"

namespace cogip {

namespace encoder {

enum class EncoderMode : uint8_t {
/// With X1 encoding, either the rising (aka leading) or the falling (aka following) edge of
/// channel A is counted. If channel A leads channel B, the rising edge is counted, and the
/// movement is forward, or clockwise. Conversely, if channel B leads channel A, the falling edge
/// is counted, and the movement is backwards, or counterclockwise.
ENCODER_MODE_X1 = 0,

/// When X2 encoding is used, both the rising and falling edges of channel A are counted. This
/// doubles the number of pulses that are counted for each rotation or linear distance, which in
/// turn doubles the encoder’s resolution.
ENCODER_MODE_X2 = 1,

/// X4 encoding goes one step further, to count both the rising and falling edges of both
/// channels A and B, which quadruples the number of pulses and increases resolution by four
/// times.
ENCODER_MODE_X4 = 2,
};

class EncoderInterface {
public:
///
/// @brief Construct a new Encoder Interface object
/// @note Encoder pulse per revolution must be set according to chosen mode
/// eg. For a 2500 PPR encoder:
/// - ENCODER_MODE_X1 -> pulse_per_rev = 2500
/// - ENCODER_MODE_X2 -> pulse_per_rev = 5000
/// - ENCODER_MODE_X4 -> pulse_per_rev = 10000
/// @param mode
/// @param pulse_per_rev
///
EncoderInterface(EncoderMode mode, int32_t pulse_per_rev): mode_(mode), pulse_per_rev_(pulse_per_rev) {}

///
/// @brief Get the pulses counted by the encoder since the last call.
///
/// @return int32_t int32_t counter value in ticks
///
virtual int32_t read_and_reset() = 0;

///
/// @brief Reset encoder counter
///
virtual void reset() = 0;

///
/// @brief Get the angle measured by the encoder since the last call.
///
/// @return double traveled angle since last call (rad).
///
double get_angle_and_reset() { return ((double)read_and_reset() / (double)pulse_per_rev_) * etl::math::pi; }

protected:
const EncoderMode mode_;
const int32_t pulse_per_rev_;
};

} /// namespace encoder

} /// namespace cogip

/// @}
86 changes: 86 additions & 0 deletions lib/encoder/include/encoder/EncoderQDEC.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#pragma once

#include "etl/math_constants.h"

// RIOT includes
#include "periph/qdec.h"

// Module includes
#include "EncoderInterface.hpp"
namespace cogip {

namespace encoder {

class EncoderQDEC : public EncoderInterface {
public:

///
/// @brief Construct a new Encoder object
/// @note Encoder pulse per revolution must be set according to chosen mode
/// eg. For a 2500 PPR encoder:
/// - ENCODER_MODE_X1 -> pulse_per_rev = 2500
/// - ENCODER_MODE_X2 -> pulse_per_rev = 5000
/// - ENCODER_MODE_X4 -> pulse_per_rev = 10000
/// @param mode
/// @param pulse_per_rev
///
explicit EncoderQDEC(uint8_t id, EncoderMode mode, int32_t pulse_per_rev): EncoderInterface(mode, pulse_per_rev), id_(id) {}

///
/// @brief Setup encoder
///
/// @return int negative on error. 0 on succes
///
int setup()
{
qdec_t qdec;
qdec_mode_t qdec_mode;

qdec = QDEC_DEV(id_);

switch (mode_) {
case EncoderMode::ENCODER_MODE_X1:
qdec_mode = QDEC_X1;
break;
case EncoderMode::ENCODER_MODE_X2:
qdec_mode = QDEC_X2;
break;
case EncoderMode::ENCODER_MODE_X4:
qdec_mode = QDEC_X4;
break;
default:
printf("Invalid QDEC mode (%u)\n", id_);
return -1;
}

/* Setup QDEC peripheral */
int error = qdec_init(qdec, qdec_mode, NULL, NULL);
if (error) {
printf("QDEC %u not initialized, error=%d !!!\n", id_, error);
}

return error;
}

///
/// @brief Get the pulses counted by the encoder since the last call.
///
/// @return int32_t counter value in ticks
///
int32_t read_and_reset() override { return qdec_read_and_reset(id_); }

///
/// @brief Reset encoder counter
///
///
void reset() override { (void)read_and_reset(); };

private:
uint8_t id_;
};

} /// namespace encoder

} /// namespace cogip

/// @}

0 comments on commit 92f42ef

Please sign in to comment.