-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I2C Mux #121
base: master
Are you sure you want to change the base?
I2C Mux #121
Changes from all commits
2da84f0
c176e2d
5e5cde9
97964fd
d24fc8d
147d1e6
99ada21
7d7d089
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -257,6 +257,57 @@ std::optional<std::unique_ptr<Repl>> Repl::fromFile(const std::string &path) | |
const auto bus = temperature["bus"].GetUint(); | ||
repl->addTemperatureCommands(bus, device_address); | ||
} | ||
|
||
// Add Mux commands | ||
if (!sensors.HasMember("mux")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux' in configuration file"); | ||
return std::nullopt; | ||
} | ||
const auto mux = sensors["mux"].GetObject(); | ||
if (!mux.HasMember("enabled")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux.enabled' in configuration file"); | ||
return std::nullopt; | ||
} | ||
if (mux["enabled"].GetBool()) { | ||
if (!mux.HasMember("bus")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux.bus' in configuration file"); | ||
return std::nullopt; | ||
} | ||
const auto bus = mux["bus"].GetUint(); | ||
if (!mux.HasMember("mux_address")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux.device_address' in configuration file"); | ||
return std::nullopt; | ||
} | ||
const auto mux_address = mux["mux_address"].GetUint(); | ||
if (!mux.HasMember("sensor_type")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux.sensor_type' in configuration file"); | ||
return std::nullopt; | ||
} | ||
const auto sensor_type = mux["sensor_type"].GetString(); | ||
if (!mux.HasMember("sensor_address")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux.sensor_address' in configuration file"); | ||
return std::nullopt; | ||
} | ||
const auto sensor_address = mux["sensor_address"].GetUint(); | ||
if (!mux.HasMember("channels")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'sensors.mux.channels' in configuration file"); | ||
return std::nullopt; | ||
} | ||
const auto channels = mux["channels"].GetArray(); | ||
std::vector<std::uint8_t> channels_vector; | ||
for (auto &channel : channels) { | ||
channels_vector.push_back(channel.GetUint()); | ||
} | ||
repl->addI2cMuxCommands(bus, mux_address, sensor_type, sensor_address, channels_vector); | ||
} | ||
|
||
if (!debugger.HasMember("motors")) { | ||
logger_.log(core::LogLevel::kFatal, | ||
"Missing required field 'debugger.motors' in configuration file"); | ||
|
@@ -644,6 +695,11 @@ void Repl::addAccelerometerCommands(const std::uint8_t bus, const std::uint8_t d | |
const auto optional_accelerometer | ||
= sensors::Accelerometer::create(logger_, i2c, bus, device_address); | ||
const auto accelerometer = std::make_shared<sensors::Accelerometer>(*optional_accelerometer); | ||
const core::Result configuration_result = *accelerometer->configure(); | ||
if (configuration_result == core::Result::kFailure) { | ||
logger_.log(core::LogLevel::kFatal, "Failed to configure the accelerometer sensor"); | ||
return; | ||
} | ||
Command accelerometer_read_command; | ||
std::stringstream identifier; | ||
identifier << "accelerometer 0x" << std::hex << static_cast<int>(device_address) << " read"; | ||
|
@@ -679,6 +735,12 @@ void Repl::addTemperatureCommands(const std::uint8_t bus, const std::uint8_t dev | |
const auto i2c = std::move(*optional_i2c); | ||
const auto optional_temperature = sensors::Temperature::create(logger_, i2c, bus, device_address); | ||
const auto temperature = std::make_shared<sensors::Temperature>(*optional_temperature); | ||
// Calibrate the temperature sensor | ||
const core::Result configuration_result = *temperature->configure(); | ||
if (configuration_result == core::Result::kFailure) { | ||
logger_.log(core::LogLevel::kFatal, "Failed to configure the temperature sensor"); | ||
return; | ||
} | ||
Command temperature_read_command; | ||
std::stringstream identifier; | ||
identifier << "temperature 0x" << std::hex << static_cast<int>(device_address) << " read"; | ||
|
@@ -700,6 +762,60 @@ void Repl::addTemperatureCommands(const std::uint8_t bus, const std::uint8_t dev | |
addCommand(temperature_read_command); | ||
} | ||
|
||
void Repl::addI2cMuxCommands(const std::uint8_t bus, | ||
const std::uint8_t mux_address, | ||
const std::string &sensor_type, | ||
const std::uint8_t sensor_address, | ||
const std::vector<std::uint8_t> &channels) | ||
{ | ||
const auto optional_i2c = getI2c(bus); | ||
if (!optional_i2c) { | ||
logger_.log(core::LogLevel::kFatal, "Failed to create I2C instance on bus %d", bus); | ||
return; | ||
} | ||
const auto i2c = std::move(*optional_i2c); | ||
if (sensor_type == "accelerometer") { | ||
// TODOLater: Figure out how to not hardcode this | ||
std::array<std::unique_ptr<sensors::II2cMuxSensor<core::RawAccelerationData>>, 4> | ||
accelerometers; | ||
for (int i = 0; i < channels.size(); i++) { | ||
const auto optional_accelerometer | ||
= sensors::Accelerometer::create(logger_, i2c, channels[i], sensor_address); | ||
accelerometers[i] | ||
= std::make_unique<sensors::Accelerometer>(std::move(*optional_accelerometer)); | ||
} | ||
// sensors::I2cMux<core::RawAccelerationData, 4> mux(logger_, i2c, mux_address, accelerometers); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? |
||
std::shared_ptr<sensors::I2cMux<core::RawAccelerationData, 4>> mux_ptr | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
= std::make_shared<sensors::I2cMux<core::RawAccelerationData, 4>>( | ||
logger_, i2c, mux_address, accelerometers); | ||
Command mux_read_command; | ||
std::stringstream identifier; | ||
identifier << "mux 0x" << std::hex << static_cast<int>(mux_address) << " read"; | ||
mux_read_command.name = identifier.str(); | ||
std::stringstream description; | ||
description << "Read mux 0x" << std::hex << static_cast<int>(mux_address) << " on " | ||
<< "I2C bus " << static_cast<int>(bus); | ||
mux_read_command.description = description.str(); | ||
mux_read_command.handler = [this, mux_ptr, bus]() { | ||
const auto value = mux_ptr->readAllChannels(); | ||
if (!value) { | ||
logger_.log(core::LogLevel::kFatal, "Failed to read the mux from bus %d", bus); | ||
} else { | ||
const std::array<core::RawAccelerationData, 4> mux_result = *value; | ||
for (int i = 0; i < mux_result.size(); i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
logger_.log(core::LogLevel::kInfo, | ||
"Accelerometer %d: \n x %d \n y %d \n z %d", | ||
i, | ||
mux_result[i].x, | ||
mux_result[i].y, | ||
mux_result[i].z); | ||
} | ||
} | ||
}; | ||
addCommand(mux_read_command); | ||
} | ||
} | ||
|
||
void Repl::addMotorControllerCommands(const std::string &bus) | ||
{ | ||
const auto optional_can = getCan(bus); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,26 +8,10 @@ std::optional<Accelerometer> Accelerometer::create(core::ILogger &logger, | |
const std::uint8_t device_address) | ||
{ | ||
if (device_address != kDefaultAccelerometerAddress | ||
|| device_address != kAlternativeAccelerometerAddress) { | ||
&& device_address != kAlternativeAccelerometerAddress) { | ||
logger.log(core::LogLevel::kFatal, "Invalid device address for accelerometer"); | ||
return std::nullopt; | ||
} | ||
// check we are communicating with the correct sensor | ||
const auto device_id = i2c->readByte(device_address, kDeviceIdAddress); | ||
if (!device_id) { | ||
logger.log(core::LogLevel::kFatal, "Failed to read the accelerometer device ID"); | ||
return std::nullopt; | ||
} | ||
if (*device_id != kExpectedDeviceIdValue) { | ||
logger.log(core::LogLevel::kFatal, "Failure, mismatched device ID for accelerometer"); | ||
return std::nullopt; | ||
} | ||
const auto ctrl1_result = i2c->writeByteToRegister(device_address, kCtrl1Address, kCtrl1Value); | ||
if (ctrl1_result == core::Result::kFailure) { return std::nullopt; }; | ||
const auto ctrl2_result = i2c->writeByteToRegister(device_address, kCtrl2Address, kCtrl2Value); | ||
if (ctrl2_result == core::Result::kFailure) { return std::nullopt; }; | ||
const auto ctrl6_result = i2c->writeByteToRegister(device_address, kCtrl6Address, kCtrl6Value); | ||
if (ctrl6_result == core::Result::kFailure) { return std::nullopt; }; | ||
return Accelerometer(logger, i2c, channel, device_address); | ||
} | ||
|
||
|
@@ -46,6 +30,28 @@ Accelerometer::~Accelerometer() | |
{ | ||
} | ||
|
||
std::optional<core::Result> Accelerometer::configure() | ||
{ | ||
// check we are communicating with the correct sensor | ||
const auto device_id = i2c_->readByte(device_address_, kDeviceIdAddress); | ||
if (!device_id) { | ||
logger_.log(core::LogLevel::kFatal, "Failed to read the accelerometer device ID"); | ||
return std::nullopt; | ||
} | ||
if (*device_id != kExpectedDeviceIdValue) { | ||
logger_.log(core::LogLevel::kFatal, "Failure, mismatched device ID for accelerometer"); | ||
return std::nullopt; | ||
} | ||
const auto ctrl1_result = i2c_->writeByteToRegister(device_address_, kCtrl1Address, kCtrl1Value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this |
||
if (ctrl1_result == core::Result::kFailure) { return std::nullopt; }; | ||
const auto ctrl2_result = i2c_->writeByteToRegister(device_address_, kCtrl2Address, kCtrl2Value); | ||
if (ctrl2_result == core::Result::kFailure) { return std::nullopt; }; | ||
const auto ctrl6_result = i2c_->writeByteToRegister(device_address_, kCtrl6Address, kCtrl6Value); | ||
if (ctrl6_result == core::Result::kFailure) { return std::nullopt; }; | ||
logger_.log(core::LogLevel::kDebug, "Successfully configured accelerometer"); | ||
return core::Result::kSuccess; | ||
} | ||
|
||
std::optional<core::Result> Accelerometer::isValueReady() | ||
{ | ||
// check to see if the values are ready to be read | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++i