From 2da84f0ca4db91e539e1d0538940713456acff69 Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Mon, 29 May 2023 14:38:50 +0100 Subject: [PATCH 1/8] Seperate configure and create on II2cMuxSensors --- lib/debug/repl.cpp | 6 ++++++ lib/sensors/accelerometer.cpp | 38 ++++++++++++++++++++-------------- lib/sensors/accelerometer.hpp | 6 ++++-- lib/sensors/i2c_mux.hpp | 7 +++++++ lib/sensors/i2c_sensors.hpp | 1 + lib/sensors/temperature.cpp | 21 ++++++++++++------- lib/sensors/temperature.hpp | 6 ++++-- lib/utils/dummy_i2c_sensor.cpp | 5 +++++ lib/utils/dummy_i2c_sensor.hpp | 1 + 9 files changed, 63 insertions(+), 28 deletions(-) diff --git a/lib/debug/repl.cpp b/lib/debug/repl.cpp index bfe780cc..c1d9c267 100644 --- a/lib/debug/repl.cpp +++ b/lib/debug/repl.cpp @@ -679,6 +679,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(*optional_temperature); + // Calibrate the temperature sensor + const core::Result calibration_result = *temperature->calibrate(); + if (calibration_result == core::Result::kFailure) { + logger_.log(core::LogLevel::kFatal, "Failed to calibrate the temperature sensor"); + return; + } Command temperature_read_command; std::stringstream identifier; identifier << "temperature 0x" << std::hex << static_cast(device_address) << " read"; diff --git a/lib/sensors/accelerometer.cpp b/lib/sensors/accelerometer.cpp index d6972743..5cc3e9f0 100644 --- a/lib/sensors/accelerometer.cpp +++ b/lib/sensors/accelerometer.cpp @@ -12,22 +12,6 @@ std::optional Accelerometer::create(core::ILogger &logger, 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 Accelerometer::calibrate() +{ + // 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; }; + logger_.log(core::LogLevel::kDebug, "Successfully configured accelerometer"); + return core::Result::kSuccess; +} + std::optional Accelerometer::isValueReady() { // check to see if the values are ready to be read diff --git a/lib/sensors/accelerometer.hpp b/lib/sensors/accelerometer.hpp index c7b962ce..4baf1dfc 100644 --- a/lib/sensors/accelerometer.hpp +++ b/lib/sensors/accelerometer.hpp @@ -29,6 +29,8 @@ class Accelerometer : public II2cMuxSensor { const std::uint8_t device_address); ~Accelerometer(); + std::optional calibrate() override; + /* * @brief Checks if the accelerometer is ready to be read * @return kSuccess if the sensor is ready to be read, @@ -37,9 +39,9 @@ class Accelerometer : public II2cMuxSensor { */ std::optional isValueReady(); - std::optional read(); + std::optional read() override; - std::uint8_t getChannel() const; + std::uint8_t getChannel() const override; private: Accelerometer(core::ILogger &logger, diff --git a/lib/sensors/i2c_mux.hpp b/lib/sensors/i2c_mux.hpp index 790a0f6e..9879665b 100644 --- a/lib/sensors/i2c_mux.hpp +++ b/lib/sensors/i2c_mux.hpp @@ -57,6 +57,13 @@ I2cMux::I2cMux(core::ILogger &logger, max_num_unusable_sensors_(static_cast(kFailureThreshold * N)) { static_assert(N <= 8, "The I2c mux can only have up to 8 channels"); + for (std::uint8_t i = 0; i < N; ++i) { + const auto &sensor = sensors_.at(i); + const auto result = sensor->calibrate(); + if (!result) { + logger_.log(core::LogLevel::kFatal, "Failed to calibrate sensor on channel %d", i); + } + } } template diff --git a/lib/sensors/i2c_sensors.hpp b/lib/sensors/i2c_sensors.hpp index 0acbb14c..e4cb37bb 100644 --- a/lib/sensors/i2c_sensors.hpp +++ b/lib/sensors/i2c_sensors.hpp @@ -16,6 +16,7 @@ class II2cMuxSensor { /* * This function carries out the initilization steps for a particular sensor. */ + virtual std::optional calibrate() = 0; virtual std::optional read() = 0; virtual std::uint8_t getChannel() const = 0; virtual ~II2cMuxSensor() {} diff --git a/lib/sensors/temperature.cpp b/lib/sensors/temperature.cpp index deae1bb1..56c95efe 100644 --- a/lib/sensors/temperature.cpp +++ b/lib/sensors/temperature.cpp @@ -12,14 +12,6 @@ std::optional Temperature::create(core::ILogger &logger, logger.log(core::LogLevel::kFatal, "Invalid device address for temperature sensor"); return std::nullopt; } - const auto write_result = i2c->writeByteToRegister(device_address, kCtrl, kConfigurationSetting); - if (write_result == core::Result::kFailure) { - logger.log( - core::LogLevel::kFatal, "Failed to configure temperature sensor at channel %d", channel); - return std::nullopt; - } - logger.log( - core::LogLevel::kDebug, "Successful to configure temperature sensor at channel %d", channel); return Temperature(logger, i2c, channel, device_address); } @@ -38,6 +30,19 @@ Temperature::~Temperature() { } +std::optional Temperature::calibrate() +{ + const auto write_result = i2c_->writeByteToRegister(device_address_, kCtrl, kConfigurationSetting); + if (write_result == core::Result::kFailure) { + logger_.log( + core::LogLevel::kFatal, "Failed to configure temperature sensor at channel %d", channel_); + return std::nullopt; + } + logger_.log( + core::LogLevel::kDebug, "Successful to configure temperature sensor at channel %d", channel_); + return core::Result::kSuccess; +} + std::optional Temperature::checkStatus() { const auto status_check_result = i2c_->readByte(device_address_, kStatus); diff --git a/lib/sensors/temperature.hpp b/lib/sensors/temperature.hpp index c3b60d39..b855969d 100644 --- a/lib/sensors/temperature.hpp +++ b/lib/sensors/temperature.hpp @@ -24,6 +24,8 @@ class Temperature : public II2cMuxSensor { ~Temperature(); + std::optional calibrate() override; + /* * @brief Checks if the temperature sensor is ready to be read * @return kSuccess if the sensor is ready to be read, @@ -35,9 +37,9 @@ class Temperature : public II2cMuxSensor { /** * @brief Reads the temperature from the sensor */ - std::optional read(); + std::optional read() override; - std::uint8_t getChannel() const; + std::uint8_t getChannel() const override ; private: Temperature(core::ILogger &logger, diff --git a/lib/utils/dummy_i2c_sensor.cpp b/lib/utils/dummy_i2c_sensor.cpp index 42934ab8..d6d64f7e 100644 --- a/lib/utils/dummy_i2c_sensor.cpp +++ b/lib/utils/dummy_i2c_sensor.cpp @@ -11,6 +11,11 @@ core::Result DummyI2cSensor::configure() return core::Result::kSuccess; } +std::optional DummyI2cSensor::calibrate() +{ + return std::nullopt; +} + std::optional DummyI2cSensor::read() { return 0; diff --git a/lib/utils/dummy_i2c_sensor.hpp b/lib/utils/dummy_i2c_sensor.hpp index 2fd6e13b..95617211 100644 --- a/lib/utils/dummy_i2c_sensor.hpp +++ b/lib/utils/dummy_i2c_sensor.hpp @@ -7,6 +7,7 @@ namespace hyped::utils { class DummyI2cSensor : public sensors::II2cMuxSensor { public: DummyI2cSensor(); + virtual std::optional calibrate(); virtual core::Result configure(); virtual std::optional read(); virtual std::uint8_t getChannel() const; From c176e2d56929f4eae032aaa57b9c145c68df1709 Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Mon, 29 May 2023 14:43:51 +0100 Subject: [PATCH 2/8] Actually select the channel for calibrate --- lib/sensors/i2c_mux.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/sensors/i2c_mux.hpp b/lib/sensors/i2c_mux.hpp index 9879665b..aef87a6a 100644 --- a/lib/sensors/i2c_mux.hpp +++ b/lib/sensors/i2c_mux.hpp @@ -59,6 +59,10 @@ I2cMux::I2cMux(core::ILogger &logger, static_assert(N <= 8, "The I2c mux can only have up to 8 channels"); for (std::uint8_t i = 0; i < N; ++i) { const auto &sensor = sensors_.at(i); + const auto channel_select_result = selectChannel(sensor->getChannel()); + if (channel_select_result == core::Result::kFailure) { + logger_.log(core::LogLevel::kFatal, "Failed to select channel %d from the i2c mux", i); + } const auto result = sensor->calibrate(); if (!result) { logger_.log(core::LogLevel::kFatal, "Failed to calibrate sensor on channel %d", i); From 5e5cde91c745f0632ce5bdc1feda293cdfb2645b Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Tue, 30 May 2023 10:34:45 +0100 Subject: [PATCH 3/8] Add to debugger and make it work? --- config/template.json | 7 +++ lib/core/types.hpp | 16 ++--- lib/debug/repl.cpp | 104 ++++++++++++++++++++++++++++++++- lib/debug/repl.hpp | 7 +++ lib/sensors/accelerometer.cpp | 2 +- lib/sensors/accelerometer.hpp | 2 +- lib/sensors/i2c_mux.hpp | 4 +- lib/sensors/i2c_sensors.hpp | 2 +- lib/sensors/temperature.cpp | 2 +- lib/sensors/temperature.hpp | 2 +- lib/utils/dummy_i2c_sensor.cpp | 7 +-- lib/utils/dummy_i2c_sensor.hpp | 3 +- 12 files changed, 132 insertions(+), 26 deletions(-) diff --git a/config/template.json b/config/template.json index deace561..9f5ae57c 100644 --- a/config/template.json +++ b/config/template.json @@ -39,6 +39,13 @@ "enabled": false, "bus": 2, "device_address": 56 + }, + "mux": { + "enabled": false, + "bus": 2, + "mux_address": 112, + "sensor_type": "accelerometer", + "channels": [0, 1, 2, 3] } }, "motors": { diff --git a/lib/core/types.hpp b/lib/core/types.hpp index e3009ccd..e0592ac8 100644 --- a/lib/core/types.hpp +++ b/lib/core/types.hpp @@ -37,10 +37,10 @@ using KeyenceData = std::array; // data produced by the accelerometer sensor // values are in milli-g (standard gravity) struct RawAccelerationData { - RawAccelerationData(const std::int32_t x, - const std::int32_t y, - const std::int32_t z, - const TimePoint measured_at) + RawAccelerationData(std::int32_t x = 0, + std::int32_t y = 0, + std::int32_t z = 0, + TimePoint measured_at = std::chrono::system_clock::now()) : x(x), y(y), z(z), @@ -48,10 +48,10 @@ struct RawAccelerationData { { } - const std::int32_t x; - const std::int32_t y; - const std::int32_t z; - const TimePoint measured_at; + std::int32_t x; + std::int32_t y; + std::int32_t z; + TimePoint measured_at; }; } // namespace hyped::core diff --git a/lib/debug/repl.cpp b/lib/debug/repl.cpp index c1d9c267..225b1ec0 100644 --- a/lib/debug/repl.cpp +++ b/lib/debug/repl.cpp @@ -257,6 +257,52 @@ std::optional> 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("channels")) { + logger_.log(core::LogLevel::kFatal, + "Missing required field 'sensors.mux.channels' in configuration file"); + return std::nullopt; + } + const auto channels = mux["channels"].GetArray(); + // Convert to vector of uint8_t + std::vector channels_vector; + for (auto &channel : channels) { + channels_vector.push_back(channel.GetUint()); + } + repl->addI2cMuxCommands(bus, mux_address, sensor_type, channels_vector); + } + if (!debugger.HasMember("motors")) { logger_.log(core::LogLevel::kFatal, "Missing required field 'debugger.motors' in configuration file"); @@ -644,6 +690,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(*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(device_address) << " read"; @@ -680,9 +731,9 @@ void Repl::addTemperatureCommands(const std::uint8_t bus, const std::uint8_t dev const auto optional_temperature = sensors::Temperature::create(logger_, i2c, bus, device_address); const auto temperature = std::make_shared(*optional_temperature); // Calibrate the temperature sensor - const core::Result calibration_result = *temperature->calibrate(); - if (calibration_result == core::Result::kFailure) { - logger_.log(core::LogLevel::kFatal, "Failed to 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; @@ -706,6 +757,53 @@ 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::vector &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>, 4> accelerometers; + for(int i = 0; i < channels.size(); i++){ + const auto optional_accelerometer = sensors::Accelerometer::create(logger_, i2c, bus, channels[i]); + accelerometers[i] = std::make_unique(std::move(*optional_accelerometer)); + } + sensors::I2cMux mux(logger_, i2c, mux_address, accelerometers); + Command mux_read_command; + std::stringstream identifier; + identifier << "mux 0x" << std::hex << static_cast(mux_address) << " read"; + mux_read_command.name = identifier.str(); + std::stringstream description; + description << "Read mux 0x" << std::hex << static_cast(mux_address) + << " on " + << "I2C bus " << static_cast(bus); + mux_read_command.description = description.str(); + mux_read_command.handler = [this, &mux, bus]() { + const auto value = mux.readAllChannels(); + if (!value) { + logger_.log(core::LogLevel::kFatal, "Failed to read the mux from bus %d", bus); + } else { + const std::array mux_result = *value; + for(int i = 0; i < mux_result.size(); i++){ + 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); + } + } + }; + } +} + void Repl::addMotorControllerCommands(const std::string &bus) { const auto optional_can = getCan(bus); diff --git a/lib/debug/repl.hpp b/lib/debug/repl.hpp index c949308f..9c7624d2 100644 --- a/lib/debug/repl.hpp +++ b/lib/debug/repl.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,8 @@ #include #include #include +#include +#include #include namespace hyped::debug { @@ -54,6 +57,10 @@ class Repl { void addSpiCommands(const std::uint8_t bus); 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 addI2cMuxCommands(const std::uint8_t bus, + const std::uint8_t mux_address, + const std::string &sensor_type, + const std::vector &channels); void addUartCommands(const std::uint8_t bus); void addMotorControllerCommands(const std::string &bus); diff --git a/lib/sensors/accelerometer.cpp b/lib/sensors/accelerometer.cpp index 5cc3e9f0..a562d342 100644 --- a/lib/sensors/accelerometer.cpp +++ b/lib/sensors/accelerometer.cpp @@ -30,7 +30,7 @@ Accelerometer::~Accelerometer() { } -std::optional Accelerometer::calibrate() +std::optional Accelerometer::configure() { // check we are communicating with the correct sensor const auto device_id = i2c_->readByte(device_address_, kDeviceIdAddress); diff --git a/lib/sensors/accelerometer.hpp b/lib/sensors/accelerometer.hpp index 4baf1dfc..02a57cc2 100644 --- a/lib/sensors/accelerometer.hpp +++ b/lib/sensors/accelerometer.hpp @@ -29,7 +29,7 @@ class Accelerometer : public II2cMuxSensor { const std::uint8_t device_address); ~Accelerometer(); - std::optional calibrate() override; + std::optional configure() override; /* * @brief Checks if the accelerometer is ready to be read diff --git a/lib/sensors/i2c_mux.hpp b/lib/sensors/i2c_mux.hpp index aef87a6a..624ecfdd 100644 --- a/lib/sensors/i2c_mux.hpp +++ b/lib/sensors/i2c_mux.hpp @@ -63,9 +63,9 @@ I2cMux::I2cMux(core::ILogger &logger, if (channel_select_result == core::Result::kFailure) { logger_.log(core::LogLevel::kFatal, "Failed to select channel %d from the i2c mux", i); } - const auto result = sensor->calibrate(); + const auto result = sensor->configure(); if (!result) { - logger_.log(core::LogLevel::kFatal, "Failed to calibrate sensor on channel %d", i); + logger_.log(core::LogLevel::kFatal, "Failed to configure sensor on channel %d", i); } } } diff --git a/lib/sensors/i2c_sensors.hpp b/lib/sensors/i2c_sensors.hpp index e4cb37bb..729afcca 100644 --- a/lib/sensors/i2c_sensors.hpp +++ b/lib/sensors/i2c_sensors.hpp @@ -16,7 +16,7 @@ class II2cMuxSensor { /* * This function carries out the initilization steps for a particular sensor. */ - virtual std::optional calibrate() = 0; + virtual std::optional configure() = 0; virtual std::optional read() = 0; virtual std::uint8_t getChannel() const = 0; virtual ~II2cMuxSensor() {} diff --git a/lib/sensors/temperature.cpp b/lib/sensors/temperature.cpp index 56c95efe..a12d3281 100644 --- a/lib/sensors/temperature.cpp +++ b/lib/sensors/temperature.cpp @@ -30,7 +30,7 @@ Temperature::~Temperature() { } -std::optional Temperature::calibrate() +std::optional Temperature::configure() { const auto write_result = i2c_->writeByteToRegister(device_address_, kCtrl, kConfigurationSetting); if (write_result == core::Result::kFailure) { diff --git a/lib/sensors/temperature.hpp b/lib/sensors/temperature.hpp index b855969d..385e8ded 100644 --- a/lib/sensors/temperature.hpp +++ b/lib/sensors/temperature.hpp @@ -24,7 +24,7 @@ class Temperature : public II2cMuxSensor { ~Temperature(); - std::optional calibrate() override; + std::optional configure() override; /* * @brief Checks if the temperature sensor is ready to be read diff --git a/lib/utils/dummy_i2c_sensor.cpp b/lib/utils/dummy_i2c_sensor.cpp index d6d64f7e..819f23a4 100644 --- a/lib/utils/dummy_i2c_sensor.cpp +++ b/lib/utils/dummy_i2c_sensor.cpp @@ -6,12 +6,7 @@ DummyI2cSensor::DummyI2cSensor() { } -core::Result DummyI2cSensor::configure() -{ - return core::Result::kSuccess; -} - -std::optional DummyI2cSensor::calibrate() +std::optional DummyI2cSensor::configure() { return std::nullopt; } diff --git a/lib/utils/dummy_i2c_sensor.hpp b/lib/utils/dummy_i2c_sensor.hpp index 95617211..52f35606 100644 --- a/lib/utils/dummy_i2c_sensor.hpp +++ b/lib/utils/dummy_i2c_sensor.hpp @@ -7,8 +7,7 @@ namespace hyped::utils { class DummyI2cSensor : public sensors::II2cMuxSensor { public: DummyI2cSensor(); - virtual std::optional calibrate(); - virtual core::Result configure(); + virtual std::optional configure(); virtual std::optional read(); virtual std::uint8_t getChannel() const; }; From 97964fd2e29c216bc805de383d7ce13b88a9b285 Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Tue, 30 May 2023 10:40:03 +0100 Subject: [PATCH 4/8] Call constructor correctly --- lib/debug/repl.cpp | 11 +++++++++-- lib/debug/repl.hpp | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/debug/repl.cpp b/lib/debug/repl.cpp index 225b1ec0..16b76722 100644 --- a/lib/debug/repl.cpp +++ b/lib/debug/repl.cpp @@ -289,6 +289,12 @@ std::optional> Repl::fromFile(const std::string &path) 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"); @@ -300,7 +306,7 @@ std::optional> Repl::fromFile(const std::string &path) for (auto &channel : channels) { channels_vector.push_back(channel.GetUint()); } - repl->addI2cMuxCommands(bus, mux_address, sensor_type, channels_vector); + repl->addI2cMuxCommands(bus, mux_address, sensor_type, sensor_address, channels_vector); } if (!debugger.HasMember("motors")) { @@ -760,6 +766,7 @@ void Repl::addTemperatureCommands(const std::uint8_t bus, const std::uint8_t dev 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 &channels) { const auto optional_i2c = getI2c(bus); @@ -772,7 +779,7 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, // TODOLater: Figure out how to not hardcode this std::array>, 4> accelerometers; for(int i = 0; i < channels.size(); i++){ - const auto optional_accelerometer = sensors::Accelerometer::create(logger_, i2c, bus, channels[i]); + const auto optional_accelerometer = sensors::Accelerometer::create(logger_, i2c, channels[i], sensor_address); accelerometers[i] = std::make_unique(std::move(*optional_accelerometer)); } sensors::I2cMux mux(logger_, i2c, mux_address, accelerometers); diff --git a/lib/debug/repl.hpp b/lib/debug/repl.hpp index 9c7624d2..da59280a 100644 --- a/lib/debug/repl.hpp +++ b/lib/debug/repl.hpp @@ -60,6 +60,7 @@ class Repl { void 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 &channels); void addUartCommands(const std::uint8_t bus); void addMotorControllerCommands(const std::string &bus); From d24fc8d9e01d2d36f8595cfdc3c9930348821466 Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Tue, 30 May 2023 10:49:11 +0100 Subject: [PATCH 5/8] Should've merged in master --- lib/sensors/accelerometer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sensors/accelerometer.cpp b/lib/sensors/accelerometer.cpp index a562d342..96ad0245 100644 --- a/lib/sensors/accelerometer.cpp +++ b/lib/sensors/accelerometer.cpp @@ -8,7 +8,7 @@ std::optional 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; } From 147d1e6a821bf6cabdc9d1b9c051ef468721e3f3 Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Tue, 30 May 2023 11:25:41 +0100 Subject: [PATCH 6/8] You actually need to add the command --- lib/debug/repl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/debug/repl.cpp b/lib/debug/repl.cpp index 16b76722..b3da6383 100644 --- a/lib/debug/repl.cpp +++ b/lib/debug/repl.cpp @@ -808,6 +808,7 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, } } }; + addCommand(mux_read_command); } } From 99ada212e142f55d6d89cff79b13301ad639bd68 Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Tue, 30 May 2023 11:45:56 +0100 Subject: [PATCH 7/8] Use shared_ptr --- lib/debug/repl.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/debug/repl.cpp b/lib/debug/repl.cpp index b3da6383..52c066e1 100644 --- a/lib/debug/repl.cpp +++ b/lib/debug/repl.cpp @@ -782,7 +782,8 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, const auto optional_accelerometer = sensors::Accelerometer::create(logger_, i2c, channels[i], sensor_address); accelerometers[i] = std::make_unique(std::move(*optional_accelerometer)); } - sensors::I2cMux mux(logger_, i2c, mux_address, accelerometers); + // sensors::I2cMux mux(logger_, i2c, mux_address, accelerometers); + std::shared_ptr> mux_ptr = std::make_shared>(logger_, i2c, mux_address, accelerometers); Command mux_read_command; std::stringstream identifier; identifier << "mux 0x" << std::hex << static_cast(mux_address) << " read"; @@ -792,8 +793,8 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, << " on " << "I2C bus " << static_cast(bus); mux_read_command.description = description.str(); - mux_read_command.handler = [this, &mux, bus]() { - const auto value = mux.readAllChannels(); + 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 { @@ -810,6 +811,7 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, }; addCommand(mux_read_command); } + } void Repl::addMotorControllerCommands(const std::string &bus) From 7d7d08983e689ac2dcc7f1756f65f4462d32b29f Mon Sep 17 00:00:00 2001 From: Kshitij Sharma Date: Tue, 30 May 2023 11:53:35 +0100 Subject: [PATCH 8/8] housekeeping --- lib/core/types.hpp | 6 +++--- lib/debug/repl.cpp | 24 +++++++++++++----------- lib/sensors/accelerometer.cpp | 2 +- lib/sensors/i2c_mux.hpp | 4 ++-- lib/sensors/i2c_sensors.hpp | 4 ++-- lib/sensors/temperature.cpp | 3 ++- lib/sensors/temperature.hpp | 2 +- 7 files changed, 24 insertions(+), 21 deletions(-) diff --git a/lib/core/types.hpp b/lib/core/types.hpp index e0592ac8..aeba9b0a 100644 --- a/lib/core/types.hpp +++ b/lib/core/types.hpp @@ -37,9 +37,9 @@ using KeyenceData = std::array; // data produced by the accelerometer sensor // values are in milli-g (standard gravity) struct RawAccelerationData { - RawAccelerationData(std::int32_t x = 0, - std::int32_t y = 0, - std::int32_t z = 0, + RawAccelerationData(std::int32_t x = 0, + std::int32_t y = 0, + std::int32_t z = 0, TimePoint measured_at = std::chrono::system_clock::now()) : x(x), y(y), diff --git a/lib/debug/repl.cpp b/lib/debug/repl.cpp index 52c066e1..43544e69 100644 --- a/lib/debug/repl.cpp +++ b/lib/debug/repl.cpp @@ -301,7 +301,6 @@ std::optional> Repl::fromFile(const std::string &path) return std::nullopt; } const auto channels = mux["channels"].GetArray(); - // Convert to vector of uint8_t std::vector channels_vector; for (auto &channel : channels) { channels_vector.push_back(channel.GetUint()); @@ -775,22 +774,26 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, return; } const auto i2c = std::move(*optional_i2c); - if (sensor_type == "accelerometer"){ + if (sensor_type == "accelerometer") { // TODOLater: Figure out how to not hardcode this - std::array>, 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(std::move(*optional_accelerometer)); + std::array>, 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(std::move(*optional_accelerometer)); } // sensors::I2cMux mux(logger_, i2c, mux_address, accelerometers); - std::shared_ptr> mux_ptr = std::make_shared>(logger_, i2c, mux_address, accelerometers); + std::shared_ptr> mux_ptr + = std::make_shared>( + logger_, i2c, mux_address, accelerometers); Command mux_read_command; std::stringstream identifier; identifier << "mux 0x" << std::hex << static_cast(mux_address) << " read"; mux_read_command.name = identifier.str(); std::stringstream description; - description << "Read mux 0x" << std::hex << static_cast(mux_address) - << " on " + description << "Read mux 0x" << std::hex << static_cast(mux_address) << " on " << "I2C bus " << static_cast(bus); mux_read_command.description = description.str(); mux_read_command.handler = [this, mux_ptr, bus]() { @@ -799,7 +802,7 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, logger_.log(core::LogLevel::kFatal, "Failed to read the mux from bus %d", bus); } else { const std::array mux_result = *value; - for(int i = 0; i < mux_result.size(); i++){ + for (int i = 0; i < mux_result.size(); i++) { logger_.log(core::LogLevel::kInfo, "Accelerometer %d: \n x %d \n y %d \n z %d", i, @@ -811,7 +814,6 @@ void Repl::addI2cMuxCommands(const std::uint8_t bus, }; addCommand(mux_read_command); } - } void Repl::addMotorControllerCommands(const std::string &bus) diff --git a/lib/sensors/accelerometer.cpp b/lib/sensors/accelerometer.cpp index 96ad0245..75c49e1e 100644 --- a/lib/sensors/accelerometer.cpp +++ b/lib/sensors/accelerometer.cpp @@ -32,7 +32,7 @@ Accelerometer::~Accelerometer() std::optional Accelerometer::configure() { - // check we are communicating with the correct sensor + // 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"); diff --git a/lib/sensors/i2c_mux.hpp b/lib/sensors/i2c_mux.hpp index 624ecfdd..ab29d075 100644 --- a/lib/sensors/i2c_mux.hpp +++ b/lib/sensors/i2c_mux.hpp @@ -58,12 +58,12 @@ I2cMux::I2cMux(core::ILogger &logger, { static_assert(N <= 8, "The I2c mux can only have up to 8 channels"); for (std::uint8_t i = 0; i < N; ++i) { - const auto &sensor = sensors_.at(i); + const auto &sensor = sensors_.at(i); const auto channel_select_result = selectChannel(sensor->getChannel()); if (channel_select_result == core::Result::kFailure) { logger_.log(core::LogLevel::kFatal, "Failed to select channel %d from the i2c mux", i); } - const auto result = sensor->configure(); + const auto result = sensor->configure(); if (!result) { logger_.log(core::LogLevel::kFatal, "Failed to configure sensor on channel %d", i); } diff --git a/lib/sensors/i2c_sensors.hpp b/lib/sensors/i2c_sensors.hpp index 729afcca..36cbd902 100644 --- a/lib/sensors/i2c_sensors.hpp +++ b/lib/sensors/i2c_sensors.hpp @@ -17,8 +17,8 @@ class II2cMuxSensor { * This function carries out the initilization steps for a particular sensor. */ virtual std::optional configure() = 0; - virtual std::optional read() = 0; - virtual std::uint8_t getChannel() const = 0; + virtual std::optional read() = 0; + virtual std::uint8_t getChannel() const = 0; virtual ~II2cMuxSensor() {} }; diff --git a/lib/sensors/temperature.cpp b/lib/sensors/temperature.cpp index a12d3281..f1c351c2 100644 --- a/lib/sensors/temperature.cpp +++ b/lib/sensors/temperature.cpp @@ -32,7 +32,8 @@ Temperature::~Temperature() std::optional Temperature::configure() { - const auto write_result = i2c_->writeByteToRegister(device_address_, kCtrl, kConfigurationSetting); + const auto write_result + = i2c_->writeByteToRegister(device_address_, kCtrl, kConfigurationSetting); if (write_result == core::Result::kFailure) { logger_.log( core::LogLevel::kFatal, "Failed to configure temperature sensor at channel %d", channel_); diff --git a/lib/sensors/temperature.hpp b/lib/sensors/temperature.hpp index 385e8ded..1ae2d5ca 100644 --- a/lib/sensors/temperature.hpp +++ b/lib/sensors/temperature.hpp @@ -39,7 +39,7 @@ class Temperature : public II2cMuxSensor { */ std::optional read() override; - std::uint8_t getChannel() const override ; + std::uint8_t getChannel() const override; private: Temperature(core::ILogger &logger,