-
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.
Add encoder interface that provide method to reset and get traveled distance since last call. Add encoder implementation for RIOT qdec driver. Signed-off-by: Mathis Lécrivain <[email protected]>
- Loading branch information
Showing
6 changed files
with
232 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,97 @@ | ||
#pragma once | ||
|
||
#include "etl/math_constants.h" | ||
|
||
// RIOT includes | ||
#include "EncoderInterface.hpp" | ||
|
||
// Module includes | ||
#include "EncoderParams.hpp" | ||
#include "periph/qdec.h" | ||
|
||
namespace cogip { | ||
|
||
namespace encoder { | ||
|
||
class Encoder : public EncoderInterface { | ||
public: | ||
Encoder(EncoderParams ¶meters) : _parameters(parameters) {} | ||
|
||
int setup() | ||
{ | ||
qdec_t qdec; | ||
qdec_mode_t mode; | ||
|
||
switch (_parameters.id()) { | ||
case EncoderID::LEFT_ENCODER_ID: | ||
qdec = QDEC_DEV(0); | ||
break; | ||
case EncoderID::RIGHT_ENCODER_ID: | ||
qdec = QDEC_DEV(1); | ||
break; | ||
default: | ||
printf("Invalid QDEC id (%u)\n", (uint8_t)_parameters.id()); | ||
return -1; | ||
} | ||
|
||
switch (_parameters.mode()) { | ||
case EncoderMode::ENCODER_MODE_X1: | ||
mode = QDEC_X1; | ||
break; | ||
case EncoderMode::ENCODER_MODE_X2: | ||
mode = QDEC_X2; | ||
break; | ||
case EncoderMode::ENCODER_MODE_X4: | ||
mode = QDEC_X4; | ||
break; | ||
default: | ||
printf("Invalid QDEC mode (%u)\n", (uint8_t)_parameters.id()); | ||
return -1; | ||
} | ||
|
||
/* Setup qdec peripheral */ | ||
int error = qdec_init(qdec, mode, NULL, NULL); | ||
if (error) { | ||
printf("QDEC %u not initialized, error=%d !!!\n", (uint8_t)_parameters.id(), error); | ||
} | ||
|
||
return error; | ||
} | ||
|
||
/** | ||
* @brief Get the distance measured by the encoder since the last call. | ||
* | ||
* @note This can become a speed in mm/Tech once periodically called. | ||
* | ||
* @return float distance in mm | ||
*/ | ||
double get_traveled_distance() | ||
{ | ||
int32_t counter = qdec_read_and_reset((qdec_t)_parameters.id()); | ||
|
||
return (double)counter / _parameters.pulse_per_rev() * | ||
(etl::math::pi * _parameters.wheel_diameter()); | ||
} | ||
|
||
/** | ||
* @brief Get the encoder raw counter value | ||
* | ||
* @return double pulse since last call | ||
*/ | ||
int32_t get_raw_counter() { return qdec_read_and_reset((qdec_t)_parameters.id()); } | ||
|
||
/** | ||
* @brief Reset encoder counter | ||
* | ||
*/ | ||
void reset() { qdec_read_and_reset((qdec_t)_parameters.id()); }; | ||
|
||
private: | ||
EncoderParams &_parameters; | ||
}; | ||
|
||
} // 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,29 @@ | ||
#pragma once | ||
|
||
namespace cogip { | ||
|
||
namespace encoder { | ||
|
||
class EncoderInterface { | ||
public: | ||
/** | ||
* @brief Get the distance measured by the encoder since the last call. | ||
* | ||
* @note This can become a speed in mm/Tech once periodically called. | ||
* | ||
* @return float distance in mm | ||
*/ | ||
virtual double get_traveled_distance() = 0; | ||
|
||
/** | ||
* @brief Reset encoder counter | ||
* | ||
*/ | ||
virtual void reset() = 0; | ||
}; | ||
|
||
} // 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,101 @@ | ||
#pragma once | ||
|
||
namespace cogip { | ||
|
||
namespace encoder { | ||
|
||
enum class EncoderID : uint8_t { | ||
LEFT_ENCODER_ID = 0, | ||
RIGHT_ENCODER_ID = 1, | ||
}; | ||
|
||
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 EncoderParams { | ||
public: | ||
/** | ||
* @brief Construct a new Encoder Params 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 id Encoder ID | ||
* @param mode Encoder mode | ||
* @param wheel_diameter Wheel diameter in millimeters | ||
* @param pulse_per_rev Encoder total pulses per revolution depending on mode choosen | ||
*/ | ||
EncoderParams(EncoderID id, EncoderMode mode, double wheel_diameter, double pulse_per_rev) | ||
: _id(id), _mode(mode), _wheel_diameter(wheel_diameter), _pulse_per_rev(pulse_per_rev) {}; | ||
|
||
/** | ||
* @brief Return encoder ID | ||
* | ||
* @note possible values: | ||
* - LEFT_ENCODER_ID | ||
* - RIGHT_ENCODER_ID | ||
* | ||
* @return EncoderID | ||
*/ | ||
EncoderID id() const { return _id; } | ||
|
||
/** | ||
* @brief Return encoder Mode | ||
* | ||
* @note possible values: | ||
* - ENCODER_MODE_X1 | ||
* - ENCODER_MODE_X2 | ||
* - ENCODER_MODE_X4 | ||
* | ||
* @return EncoderMode | ||
*/ | ||
EncoderMode mode() const { return _mode; } | ||
|
||
/** | ||
* @brief Return encoder wheel diameter value in mm. | ||
* | ||
* @return double | ||
*/ | ||
double wheel_diameter() const { return _wheel_diameter; } | ||
|
||
/** | ||
* @brief Return encoder pulse per revolution | ||
* | ||
* @return double | ||
*/ | ||
double pulse_per_rev() const { return _pulse_per_rev; } | ||
|
||
private: | ||
EncoderID _id; | ||
EncoderMode _mode; | ||
double _wheel_diameter; | ||
double _pulse_per_rev; | ||
}; | ||
|
||
} // namespace encoder | ||
|
||
} // namespace cogip | ||
|
||
/// @} |