Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
"enabled": false,
"bus": 2,
"device_address": 56
},
"wheel_encoders": {
"enabled": false,
"pin": 0
}
},
"motors": {
Expand Down
84 changes: 84 additions & 0 deletions lib/debug/repl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,26 @@ std::optional<std::unique_ptr<Repl>> Repl::fromFile(const std::string &path)
const auto bus = motor_controller["bus"].GetString();
repl->addMotorControllerCommands(bus);
}
if (!sensors.HasMember("wheel_encoders")) {
logger_.log(core::LogLevel::kFatal,
"Missing required field 'sensors.wheel_encoders' in configuration file");
return std::nullopt;
}
const auto wheel_encoders = sensors["wheel_encoders"].GetObject();
if (!wheel_encoders.HasMember("enabled")) {
logger_.log(core::LogLevel::kFatal,
"Missing required field 'sensors.wheel_encoders.enabled' in configuration file");
return std::nullopt;
}
if (wheel_encoders["enabled"].GetBool()) {
if (!wheel_encoders.HasMember("pin")) {
logger_.log(core::LogLevel::kFatal,
"Missing required field 'sensors.wheel_encoders.pin' in configuration file");
return std::nullopt;
}
const auto pin = wheel_encoders["pin"].GetUint();
repl->addWheelEncoderCommands(pin);
}
return repl;
}

Expand Down Expand Up @@ -879,6 +899,70 @@ void Repl::addMotorControllerCommands(const std::string &bus)
addCommand(frequency_time_command);
}

void Repl::addWheelEncoderCommands(const std::uint8_t pin)
{
const auto optional_adc = getAdc(pin);
if (!optional_adc) {
logger_.log(core::LogLevel::kFatal, "Failed to create ADC instance on pin %d", pin);
return;
}
const auto adc = std::move(*optional_adc);
const auto wheel_encoder = std::make_shared<sensors::WheelEncoder>(logger_, adc);
{
Command wheel_encoder_read_count_command;
std::stringstream identifier;
identifier << "wheel encoder count";
wheel_encoder_read_count_command.name = identifier.str();
std::stringstream description;
description << "Read count wheel encoder";
wheel_encoder_read_count_command.description = description.str();
wheel_encoder_read_count_command.handler = [this, wheel_encoder]() {
const auto count = wheel_encoder->getCount();
logger_.log(core::LogLevel::kInfo, "Wheel encoder value: %d", count);
};
addCommand(wheel_encoder_read_count_command);
}
{
Command wheel_encoder_reset_count_command;
std::stringstream identifier;
identifier << "wheel encoder reset";
wheel_encoder_reset_count_command.name = identifier.str();
std::stringstream description;
description << "Reset wheel encoder count";
wheel_encoder_reset_count_command.description = description.str();
wheel_encoder_reset_count_command.handler = [this, wheel_encoder]() {
wheel_encoder->resetCount();
logger_.log(core::LogLevel::kInfo, "Wheel encoder count reset");
};
addCommand(wheel_encoder_reset_count_command);
}
{
Command wheel_encoder_run_command;
std::stringstream identifier;
identifier << "wheel encoder run";
wheel_encoder_run_command.name = identifier.str();
std::stringstream description;
description << "Run wheel encoder";
wheel_encoder_run_command.description = description.str();
wheel_encoder_run_command.handler = [this, wheel_encoder]() {
std::uint64_t previous_wheel_encoder_count_ = 0;
while (1) {
const auto result = wheel_encoder->updateCount();
if (result == core::Result::kFailure) {
logger_.log(core::LogLevel::kFatal, "Failed to update wheel encoder count");
break;
}
const std::uint64_t count = wheel_encoder->getCount();
if (count != previous_wheel_encoder_count_) {
logger_.log(core::LogLevel::kInfo, "Wheel encoder value: %jd", count);
previous_wheel_encoder_count_ = count;
}
}
};
addCommand(wheel_encoder_run_command);
}
}

std::optional<std::shared_ptr<io::IAdc>> Repl::getAdc(const std::uint8_t bus)
{
const auto adc = adc_.find(bus);
Expand Down
2 changes: 2 additions & 0 deletions lib/debug/repl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <motors/time_frequency_calculator.hpp>
#include <sensors/accelerometer.hpp>
#include <sensors/temperature.hpp>
#include <sensors/wheel_encoder.hpp>

namespace hyped::debug {

Expand Down Expand Up @@ -55,6 +56,7 @@ class Repl {
void addAccelerometerCommands(const std::uint8_t bus, const std::uint8_t device_address);
void addTemperatureCommands(const std::uint8_t bus, const std::uint8_t device_address);
void addUartCommands(const std::uint8_t bus);
void addWheelEncoderCommands(const std::uint8_t pin);
void addMotorControllerCommands(const std::string &bus);

/**
Expand Down
36 changes: 36 additions & 0 deletions lib/sensors/wheel_encoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "wheel_encoder.hpp"

namespace hyped::sensors {

WheelEncoder::WheelEncoder(core::ILogger &logger, std::shared_ptr<io::IAdc> adc)
: logger_(logger),
adc_(adc),
count_(0),
previous_voltage_(0)
{
}

std::uint64_t WheelEncoder::getCount()
{
return count_;
}

core::Result WheelEncoder::updateCount()
{
const auto optional_voltage = adc_->readValue();
if (!optional_voltage) {
logger_.log(core::LogLevel::kFatal, "Failed to read wheel encoder value from ADC");
return core::Result::kFailure;
}
const core::Float voltage = *optional_voltage;
if (voltage > kVoltageThreshold && previous_voltage_ < kVoltageThreshold) { count_++; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++count_

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix this, however can you remind me what the reason for this is

previous_voltage_ = voltage;
return core::Result::kSuccess;
Comment on lines +26 to +28

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we keep getting a value over the thresh, at what point do we think the encoders aren't working. Ik nav pays a lot of attention to these so want to make sure we report any possible failure asap.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah these are our singular most accurate sensor I think. If these give faulty data, we'll only spot it if it's disagreeing with our other data but this data being unreliable could potentially leave us without a ground truth

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it depends on velocity. we can probably calculate a maximum high period before we stop trusting it based off of minimum velocity we expect to hold

}

void WheelEncoder::resetCount()
{
count_ = 0;
}

} // namespace hyped::sensors
24 changes: 24 additions & 0 deletions lib/sensors/wheel_encoder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once
#include <memory>
#include <optional>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#include <cstdint>


#include <core/logger.hpp>
#include <core/types.hpp>
#include <io/adc.hpp>

namespace hyped::sensors {
class WheelEncoder {
public:
WheelEncoder(core::ILogger &logger, std::shared_ptr<io::IAdc> adc);
std::uint64_t getCount();
core::Result updateCount();
void resetCount();

private:
static constexpr core::Float kVoltageThreshold = 1.7;
core::ILogger &logger_;
std::shared_ptr<io::IAdc> adc_;
std::uint64_t count_;
core::Float previous_voltage_;
};
} // namespace hyped::sensors