/* * peripherals_ir_sensors.hpp * * Created on: Apr 10, 2021 * Author: erki */ #ifndef PERIPHERALS_IR_SENSORS_HPP_ #define PERIPHERALS_IR_SENSORS_HPP_ #include #include #include #include namespace Peripherals { template class IrSensors { public: using gpio = G; Adc adc; IrSensors() = delete; template explicit IrSensors(ADC_HandleTypeDef* hadc, const std::array& channels, Args&&... gpios) : adc(hadc), _channels(channels), _gpios{std::forward(gpios)...} { static_assert(sizeof...(Args) == N, "Not enough GPIOs passed."); } void startReading() { for (auto& gpio : _gpios) gpio.Set(true); adc.startDma(); } void stopReading() { for (auto& gpio : _gpios) gpio.Set(false); adc.stopDma(); } void updateReadings() { for (std::size_t i = 0; i < N; i++) { _averages[i] -= _averages[i] / Average; _averages[i] += adc.readings[i] / Average; } } std::array, N> getDistanceData() { std::array, N> data; for (std::size_t i = 0; i < N; i++) { const float interim = _averages[i] - _offsets[i]; data[i].first = _multipliers[i] * std::pow(interim, _exponents[i]); data[i].second = data[i].first < _wall_thresholds[i]; } return data; } void calibrate(const std::uint32_t samples, const std::uint32_t sample_time) { std::array measurements; for (std::uint32_t i = 0; i < samples; i++) { for (std::uint32_t ch = 0; ch < _channels.size(); ch++) measurements[ch] += adc.read(_channels[ch], sample_time, 100); } for (std::uint32_t ch = 0; ch < _channels.size(); ch++) _offsets[ch] = std::uint16_t(measurements[ch] / samples); } void setExponents(const std::array& e) { _exponents = e; } void setMultipliers(const std::array& m) { _multipliers = m; } void setWallThresholds(const std::array& t) { _wall_thresholds = t; } private: std::array _channels; std::array _gpios; std::array _averages; std::array _offsets; std::array _exponents; std::array _multipliers; std::array _wall_thresholds; }; }// namespace Peripherals #endif /* PERIPHERALS_IR_SENSORS_HPP_ */