Skip to content

Commit 9efb83e

Browse files
authored
Fix direction not being correctly calculated (#15)
There were several issues when calculating/detecting the direction of movement with DirectionalOdometer. Specifically, the first problem was that the interrupt was triggered to be invoked on pin state change instead of a rising edge which was the initial intention. Additionally, determining the distance should only be done within the interrupt, since the state of the direction pin is only meaningful when the pulse pin is on a falling or rising edge.
2 parents d7dd321 + 776c6db commit 9efb83e

File tree

7 files changed

+39
-29
lines changed

7 files changed

+39
-29
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Smartcar shield
2-
version=5.0.0
2+
version=5.0.1
33
author=Dimitris Platis
44
maintainer=Dimitris Platis <dimitris@plat.is>
55
sentence=Arduino library for controlling the Smartcar platform

src/sensors/odometer/interrupt/DirectionalOdometer.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ const uint8_t kInput = 0;
88
using namespace smartcarlib::constants::odometer;
99

1010
DirectionalOdometer::DirectionalOdometer(uint8_t directionPin,
11-
uint8_t pinStateWhenForward,
11+
int pinStateWhenForward,
1212
unsigned long pulsesPerMeter,
1313
Runtime& runtime)
1414
: DirectionlessOdometer(pulsesPerMeter, runtime)
1515
, mDirectionPin{ directionPin }
1616
, mPinStateWhenForward{ pinStateWhenForward }
1717
, mRuntime(runtime)
18-
, mNegativePulsesCounter{ 0 }
1918
{
2019
}
2120

@@ -44,10 +43,12 @@ void DirectionalOdometer::update()
4443
}
4544

4645
DirectionlessOdometer::update();
47-
if (mRuntime.getPinState(mDirectionPin) != mPinStateWhenForward)
46+
const auto directionPinState = mRuntime.getPinState(mDirectionPin);
47+
if (directionPinState != mPinStateWhenForward)
4848
{
4949
mNegativePulsesCounter++;
5050
}
51+
mDirection = directionPinState;
5152
}
5253

5354
long DirectionalOdometer::getDistance()
@@ -72,11 +73,10 @@ float DirectionalOdometer::getSpeed()
7273
return DirectionlessOdometer::getSpeed() * getDirection();
7374
}
7475

75-
int8_t DirectionalOdometer::getDirection()
76+
int8_t DirectionalOdometer::getDirection() const
7677
{
77-
return mRuntime.getPinState(mDirectionPin) == mPinStateWhenForward
78-
? smartcarlib::constants::odometer::kForward
79-
: smartcarlib::constants::odometer::kBackward;
78+
return mDirection == mPinStateWhenForward ? smartcarlib::constants::odometer::kForward
79+
: smartcarlib::constants::odometer::kBackward;
8080
}
8181

8282
bool DirectionalOdometer::providesDirection()

src/sensors/odometer/interrupt/DirectionalOdometer.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ class DirectionalOdometer : public DirectionlessOdometer
2828
* \endcode
2929
*/
3030
DirectionalOdometer(uint8_t directionPin,
31-
uint8_t pinStateWhenForward,
31+
int pinStateWhenForward,
3232
unsigned long pulsesPerMeter,
3333
Runtime& runtime = arduinoRuntime);
3434
#else
3535
DirectionalOdometer(uint8_t directionPin,
36-
uint8_t pinStateWhenForward,
36+
int pinStateWhenForward,
3737
unsigned long pulsesPerMeter,
3838
Runtime& runtime);
3939
#endif
@@ -66,12 +66,12 @@ class DirectionalOdometer : public DirectionlessOdometer
6666
* unsigned short direction = odometer.getDirection();
6767
* \endcode
6868
*/
69-
int8_t getDirection();
70-
69+
int8_t getDirection() const;
7170

7271
private:
7372
const uint8_t mDirectionPin;
74-
const uint8_t mPinStateWhenForward;
73+
const int mPinStateWhenForward;
7574
Runtime& mRuntime;
76-
volatile unsigned long mNegativePulsesCounter;
75+
volatile unsigned long mNegativePulsesCounter{ 0 };
76+
volatile int mDirection{ smartcarlib::constants::odometer::kForward };
7777
};

src/sensors/odometer/interrupt/DirectionlessOdometer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace
66
{
77
const int8_t kNotAnInterrupt = -1;
8-
const uint8_t kRisingEdge = 1;
8+
const uint8_t kRisingEdge = 3;
99
const uint8_t kInput = 0;
1010
const unsigned long kMinimumPulseGap = 700;
1111
const float kMillisecondsInSecond = 1000.0;

test/build_and_run_ut.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fi
1313
mkdir -p build
1414
cd build
1515
cmake -DCMAKE_BUILD_TYPE=Debug ..
16-
make
16+
make -j$(nproc)
1717
ctest
1818

1919
# Go back to the initial directory when you are done

test/ut/DirectionalOdometer_test.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,21 @@ TEST_F(DirectionalOdometerAttachedTest, getDistance_WhenCalled_WillReturnCorrect
136136
EXPECT_EQ(mDirectionalOdometer.getDistance(), 0);
137137
}
138138

139-
TEST_F(DirectionalOdometerBasicTest, getDirection_WhenPinStateForward_WillReturnForward)
139+
TEST_F(DirectionalOdometerAttachedTest, getDirection_WhenPinStateForward_WillReturnForward)
140140
{
141141
EXPECT_CALL(mRuntime, getPinState(kDirectionPin)).WillOnce(Return(kPinStateWhenForward));
142142

143+
mDirectionalOdometer.update();
144+
143145
EXPECT_EQ(mDirectionalOdometer.getDirection(), smartcarlib::constants::odometer::kForward);
144146
}
145147

146-
TEST_F(DirectionalOdometerBasicTest, getDirection_WhenPinStateBackward_WillReturnBackward)
148+
TEST_F(DirectionalOdometerAttachedTest, getDirection_WhenPinStateBackward_WillReturnBackward)
147149
{
148150
EXPECT_CALL(mRuntime, getPinState(kDirectionPin)).WillOnce(Return(!kPinStateWhenForward));
149151

152+
mDirectionalOdometer.update();
153+
150154
EXPECT_EQ(mDirectionalOdometer.getDirection(), smartcarlib::constants::odometer::kBackward);
151155
}
152156

@@ -178,7 +182,7 @@ TEST_F(DirectionalOdometerAttachedTest, getSpeed_WhenCalled_WillReturnCorrectSpe
178182
unsigned long firstPulse = 1000;
179183
unsigned long secondPulse = 21000;
180184
EXPECT_CALL(mRuntime, getPinState(kDirectionPin))
181-
.Times(3)
185+
.Times(2)
182186
.WillRepeatedly(Return(!kPinStateWhenForward));
183187
{
184188
InSequence seq;

test/ut/DirectionlessOdometer_test.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
#include "gmock/gmock.h"
22
#include "gtest/gtest.h"
33

4-
#include "MockRuntime.hpp"
54
#include "DirectionlessOdometer.hpp"
5+
#include "MockRuntime.hpp"
66

77
using namespace ::testing;
88
using namespace smartcarlib::constants::odometer;
99

1010
namespace
1111
{
12-
const int8_t kNotAnInterrupt = -1;
13-
const int8_t kAnInterrupt = 1;
14-
const uint8_t kRisingEdge = 1;
15-
const uint8_t kInput = 0;
16-
const unsigned long kMinimumPulseGap = 700;
12+
const int8_t kNotAnInterrupt = -1;
13+
const int8_t kAnInterrupt = 1;
14+
const uint8_t kRisingEdge = 3;
15+
const uint8_t kInput = 0;
16+
const unsigned long kMinimumPulseGap = 700;
1717
} // namespace
1818

1919
class DirectionlessOdometerBasicTest : public Test
@@ -56,10 +56,14 @@ class DirectionlessOdometerAttachedTest : public DirectionlessOdometerBasicTest
5656
class DirectionlessOdometerBadPulsesPerMeter : public DirectionlessOdometerBasicTest
5757
{
5858
public:
59-
DirectionlessOdometerBadPulsesPerMeter() : DirectionlessOdometerBasicTest(0) {}
59+
DirectionlessOdometerBadPulsesPerMeter()
60+
: DirectionlessOdometerBasicTest(0)
61+
{
62+
}
6063
};
6164

62-
TEST_F(DirectionlessOdometerBadPulsesPerMeter, constructor_WhenCalledWithZeroPulsesPerMeter_WillNotDivideByZero)
65+
TEST_F(DirectionlessOdometerBadPulsesPerMeter,
66+
constructor_WhenCalledWithZeroPulsesPerMeter_WillNotDivideByZero)
6367
{
6468
// Providing `0` as the argument to pulses per meter should not cause the constructor
6569
// to crash due to a division by zero
@@ -191,7 +195,8 @@ TEST_F(DirectionlessOdometerAttachedTest, update_WhenPulsesTooClose_WillIgnorePu
191195
EXPECT_EQ(mDirectionlessOdometer.getDistance(), initialDistance);
192196
}
193197

194-
TEST_F(DirectionlessOdometerAttachedTest, update_WhenFirstPulseArrives_WillCalculateDistanceButNotSpeed)
198+
TEST_F(DirectionlessOdometerAttachedTest,
199+
update_WhenFirstPulseArrives_WillCalculateDistanceButNotSpeed)
195200
{
196201
unsigned long firstPulse = 2000;
197202
EXPECT_CALL(mRuntime, currentTimeMicros()).WillOnce(Return(firstPulse));
@@ -202,7 +207,8 @@ TEST_F(DirectionlessOdometerAttachedTest, update_WhenFirstPulseArrives_WillCalcu
202207
EXPECT_FLOAT_EQ(mDirectionlessOdometer.getSpeed(), 0);
203208
}
204209

205-
TEST_F(DirectionlessOdometerAttachedTest, update_WhenFirstPulseArrivesFast_WillCalculateDistanceButNotSpeed)
210+
TEST_F(DirectionlessOdometerAttachedTest,
211+
update_WhenFirstPulseArrivesFast_WillCalculateDistanceButNotSpeed)
206212
{
207213
unsigned long firstPulse = kMinimumPulseGap - 1;
208214
EXPECT_CALL(mRuntime, currentTimeMicros()).WillOnce(Return(firstPulse));

0 commit comments

Comments
 (0)