From 0d4e603a647ab171a7e8524a8918351f557d00b6 Mon Sep 17 00:00:00 2001 From: fastium Date: Tue, 29 Oct 2024 16:15:32 +0100 Subject: [PATCH] ADD speedometer and gear class --- common/speedometer.cpp | 125 ++++++++++++++++++++++++++++++ common/speedometer.hpp | 91 ++++++++++++++++++++++ static_scheduling/gear_device.cpp | 83 ++++++++++++++++++++ static_scheduling/gear_device.hpp | 50 ++++++++++++ 4 files changed, 349 insertions(+) create mode 100644 common/speedometer.cpp create mode 100644 common/speedometer.hpp create mode 100644 static_scheduling/gear_device.cpp create mode 100644 static_scheduling/gear_device.hpp diff --git a/common/speedometer.cpp b/common/speedometer.cpp new file mode 100644 index 0000000..a30ecaa --- /dev/null +++ b/common/speedometer.cpp @@ -0,0 +1,125 @@ +// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/**************************************************************************** + * @file speedometer_device.cpp + * @author Serge Ayer + * + * @brief WheelCounterDevice implementation (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#include "speedometer.hpp" + +#include +#include + +// from disco_h747i/wrappers +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "Speedometer" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace bike_computer { + +Speedometer::Speedometer(Timer& timer) : _timer(timer) { + // update _lastTime + _lastTime = _timer.elapsed_time(); +} + +void Speedometer::setCurrentRotationTime( + const std::chrono::milliseconds& currentRotationTime) { + if (_pedalRotationTime != currentRotationTime) { + // compute distance before changing the rotation time + computeDistance(); + + // change pedal rotation time + _pedalRotationTime = currentRotationTime; + + // compute speed with the new pedal rotation time + computeSpeed(); + } +} + +void Speedometer::setGearSize(uint8_t gearSize) { + if (_gearSize != gearSize) { + // compute distance before chaning the gear size + computeDistance(); + + // change gear size + _gearSize = gearSize; + + // compute speed with the new gear size + computeSpeed(); + } +} + +float Speedometer::getCurrentSpeed() const { return _currentSpeed; } + +float Speedometer::getDistance() { + // make sure to update the distance traveled + computeDistance(); + return _totalDistance; +} + +void Speedometer::reset() { + // TODO : done + this->_totalDistanceMutex.lock(); + this->_totalDistance = 0.0f; + this->_totalDistanceMutex.unlock(); +} + +#if defined(MBED_TEST_MODE) +uint8_t Speedometer::getGearSize() const { return _gearSize; } + +float Speedometer::getWheelCircumference() const { return kWheelCircumference; } + +float Speedometer::getTraySize() const { return kTraySize; } + +std::chrono::milliseconds Speedometer::getCurrentPedalRotationTime() const { + return _pedalRotationTime; +} + +#endif // defined(MBED_TEST_MODE) + +void Speedometer::computeSpeed() { + // For computing the speed given a rear gear (braquet), one must divide the size of + // the tray (plateau) by the size of the rear gear (pignon arrière), and then multiply + // the result by the circumference of the wheel. Example: tray = 50, rear gear = 15. + // Distance run with one pedal turn (wheel circumference = 2.10 m) = 50/15 * 2.1 m + // = 6.99m If you ride at 80 pedal turns / min, you run a distance of 6.99 * 80 / min + // ~= 560 m / min = 33.6 km/h + + // TODO + + +} + +void Speedometer::computeDistance() { + // For computing the speed given a rear gear (braquet), one must divide the size of + // the tray (plateau) by the size of the rear gear (pignon arrière), and then multiply + // the result by the circumference of the wheel. Example: tray = 50, rear gear = 15. + // Distance run with one pedal turn (wheel circumference = 2.10 m) = 50/15 * 2.1 m + // = 6.99m If you ride at 80 pedal turns / min, you run a distance of 6.99 * 80 / min + // ~= 560 m / min = 33.6 km/h. We then multiply the speed by the time for getting the + // distance traveled. + + // TODO +} + +} // namespace bike_computer \ No newline at end of file diff --git a/common/speedometer.hpp b/common/speedometer.hpp new file mode 100644 index 0000000..bbc1e6b --- /dev/null +++ b/common/speedometer.hpp @@ -0,0 +1,91 @@ +// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/**************************************************************************** + * @file speedometer_device.hpp + * @author Serge Ayer + * + * @brief WheelCounterDevice header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace bike_computer { + +class Speedometer { + public: + explicit Speedometer(Timer& timer); // NOLINT(runtime/references) + + // method used for setting the current pedal rotation time + void setCurrentRotationTime(const std::chrono::milliseconds& currentRotationTime); + + // method used for setting/getting the current gear + void setGearSize(uint8_t gearSize); + + // method called for getting the current speed (expressed in km / h) + float getCurrentSpeed() const; + + // method called for getting the current traveled distance (expressed in km) + float getDistance(); + + // method called for resetting the traveled distance + void reset(); + + // methods used for tests only +#if defined(MBED_TEST_MODE) + uint8_t getGearSize() const; + float getWheelCircumference() const; + float getTraySize() const; + std::chrono::milliseconds getCurrentPedalRotationTime() const; + void setOnResetCallback(mbed::Callback cb); +#endif // defined(MBED_TEST_MODE) + + private: + // private methods + void computeSpeed(); + void computeDistance(); + + // definition of task period time + static constexpr std::chrono::milliseconds kTaskPeriod = 400ms; + // definition of task execution time + static constexpr std::chrono::microseconds kTaskRunTime = 200000us; + + // constants related to speed computation + static constexpr float kWheelCircumference = 2.1f; + static constexpr uint8_t kTraySize = 50; + std::chrono::microseconds _lastTime = std::chrono::microseconds::zero(); + std::chrono::milliseconds _pedalRotationTime = kInitialPedalRotationTime; + + // data members + Timer& _timer; + LowPowerTicker _ticker; + float _currentSpeed = 0.0f; + Mutex _totalDistanceMutex; + float _totalDistance = 0.0f; + uint8_t _gearSize = 1; + + Thread _thread; + +#if defined(MBED_TEST_MODE) + mbed::Callback _cb; +#endif +}; + +} // namespace bike_computer \ No newline at end of file diff --git a/static_scheduling/gear_device.cpp b/static_scheduling/gear_device.cpp new file mode 100644 index 0000000..e120ce2 --- /dev/null +++ b/static_scheduling/gear_device.cpp @@ -0,0 +1,83 @@ +// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/**************************************************************************** + * @file gear_device.cpp + * @author Serge Ayer + * + * @brief Gear Device implementation (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#include "gear_device.hpp" + +// from disco_h747i/wrappers +#include + +#include "joystick.hpp" +#include "mbed_trace.h" + +#if MBED_CONF_MBED_TRACE_ENABLE +#define TRACE_GROUP "GearDevice" +#endif // MBED_CONF_MBED_TRACE_ENABLE + +namespace static_scheduling { + +// definition of task execution time +static constexpr std::chrono::microseconds kTaskRunTime = 100000us; + +GearDevice::GearDevice(Timer& timer) : _timer(timer) {} + +uint8_t GearDevice::getCurrentGear() { + std::chrono::microseconds initialTime = _timer.elapsed_time(); + std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); + // we bound the change to one increment/decrement per call + bool hasChanged = false; + while (elapsedTime < kTaskRunTime) { + if (!hasChanged) { + disco::Joystick::State joystickState = + disco::Joystick::getInstance().getState(); + switch (joystickState) { + case disco::Joystick::State::UpPressed: + if (_currentGear < bike_computer::kMaxGear) { + _currentGear++; + } + hasChanged = true; + break; + + case disco::Joystick::State::DownPressed: + if (_currentGear > bike_computer::kMinGear) { + _currentGear--; + } + hasChanged = true; + break; + + default: + break; + } + } + elapsedTime = _timer.elapsed_time() - initialTime; + } + return _currentGear; +} + +uint8_t GearDevice::getCurrentGearSize() const { + // simulate task computation by waiting for the required task run time + // wait_us(kTaskRunTime.count()); + return bike_computer::kMaxGearSize - _currentGear; +} + +} // namespace static_scheduling \ No newline at end of file diff --git a/static_scheduling/gear_device.hpp b/static_scheduling/gear_device.hpp new file mode 100644 index 0000000..d44d6f7 --- /dev/null +++ b/static_scheduling/gear_device.hpp @@ -0,0 +1,50 @@ +// Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/**************************************************************************** + * @file gear_device.hpp + * @author Serge Ayer + * + * @brief Gear Device header file (static scheduling) + * + * @date 2023-08-20 + * @version 1.0.0 + ***************************************************************************/ + +#pragma once + +#include "constants.hpp" +#include "mbed.h" + +namespace static_scheduling { + +class GearDevice { + public: + explicit GearDevice(Timer& timer); // NOLINT(runtime/references) + + // make the class non copyable + GearDevice(GearDevice&) = delete; + GearDevice& operator=(GearDevice&) = delete; + + // method called for updating the bike system + uint8_t getCurrentGear(); + uint8_t getCurrentGearSize() const; + + private: + // data members + uint8_t _currentGear = bike_computer::kMinGear; + Timer& _timer; +}; + +} // namespace static_scheduling \ No newline at end of file