Skip to content

Commit ac95473

Browse files
authored
Merge pull request #16 from 4ms/quadrature_encoder
Quadrature encoder
2 parents 336e2c4 + d82a4d8 commit ac95473

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

tests/quadrature_encoder_tests.cc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "doctest.h"
2+
#include "util/quadrature_encoder.hh"
3+
4+
TEST_CASE("Quadrature Encoder") {
5+
6+
using Enc = QuadratureEncoder<>;
7+
8+
Enc encoder{};
9+
10+
// check clockwise
11+
CHECK(encoder.get_motion(true, false) == Enc::None);
12+
CHECK(encoder.get_motion(false, false) == Enc::None);
13+
CHECK(encoder.get_motion(false, true) == Enc::None);
14+
CHECK(encoder.get_motion(true, true) == Enc::CW);
15+
16+
// check clockwise no state change
17+
CHECK(encoder.get_motion(true, false) == Enc::None);
18+
CHECK(encoder.get_motion(true, false) == Enc::None);
19+
CHECK(encoder.get_motion(true, false) == Enc::None);
20+
CHECK(encoder.get_motion(true, false) == Enc::None);
21+
22+
CHECK(encoder.get_motion(false, false) == Enc::None);
23+
CHECK(encoder.get_motion(false, false) == Enc::None);
24+
CHECK(encoder.get_motion(false, false) == Enc::None);
25+
CHECK(encoder.get_motion(false, false) == Enc::None);
26+
27+
CHECK(encoder.get_motion(false, true) == Enc::None);
28+
CHECK(encoder.get_motion(false, true) == Enc::None);
29+
CHECK(encoder.get_motion(false, true) == Enc::None);
30+
CHECK(encoder.get_motion(false, true) == Enc::None);
31+
32+
CHECK(encoder.get_motion(true, true) == Enc::CW);
33+
CHECK(encoder.get_motion(true, true) == Enc::None);
34+
CHECK(encoder.get_motion(true, true) == Enc::None);
35+
CHECK(encoder.get_motion(true, true) == Enc::None);
36+
37+
// check counter-clockwise
38+
CHECK(encoder.get_motion(false, true) == Enc::None);
39+
CHECK(encoder.get_motion(false, false) == Enc::None);
40+
CHECK(encoder.get_motion(true, false) == Enc::None);
41+
CHECK(encoder.get_motion(true, true) == Enc::CCW);
42+
43+
// check with no state change
44+
CHECK(encoder.get_motion(false, true) == Enc::None);
45+
CHECK(encoder.get_motion(false, true) == Enc::None);
46+
47+
CHECK(encoder.get_motion(false, false) == Enc::None);
48+
CHECK(encoder.get_motion(false, false) == Enc::None);
49+
50+
CHECK(encoder.get_motion(true, false) == Enc::None);
51+
CHECK(encoder.get_motion(true, false) == Enc::None);
52+
53+
CHECK(encoder.get_motion(true, true) == Enc::CCW);
54+
CHECK(encoder.get_motion(true, true) == Enc::None);
55+
}

util/quadrature_encoder.hh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
template<bool invert = false>
6+
class QuadratureEncoder {
7+
static constexpr uint8_t valid_ccw = 0b10000111 ^ (invert ? 0xff : 0x00);
8+
static constexpr uint8_t valid_cw = 0b01001011 ^ (invert ? 0xff : 0x00);
9+
10+
uint8_t prev_state{};
11+
12+
public:
13+
enum Direction { None = 0, CW = 1, CCW = -1 };
14+
15+
Direction get_motion(bool state_a, bool state_b) {
16+
const auto cur_state = state_a | (state_b << 1u);
17+
18+
if ((prev_state & 0b11) == cur_state)
19+
return None;
20+
21+
prev_state <<= 2;
22+
prev_state |= cur_state;
23+
24+
switch (prev_state) {
25+
case valid_cw:
26+
return CW;
27+
case valid_ccw:
28+
return CCW;
29+
default:
30+
return None;
31+
}
32+
}
33+
};

0 commit comments

Comments
 (0)