-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #171 from cogip/170-motion-control-add-c++-encoder…
…-class 170 motion control add c++ encoder class
- Loading branch information
Showing
5 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Board features required | ||
FEATURES_REQUIRED += periph_qdec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
/// @} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
/// @} |