Motors, PWM, and utility modules

This commit is contained in:
Erki 2021-03-05 14:54:21 +02:00
parent 55e2fbb490
commit fe499d69f0
9 changed files with 421 additions and 0 deletions

View File

@ -0,0 +1,17 @@
/*
* peripherals_config.h
*
* Created on: Feb 24, 2021
* Author: erki
*/
#ifndef PERIPHERALS_CONFIG_HPP_
#define PERIPHERALS_CONFIG_HPP_
#define PERIPHERALS_USE_DELAY_US
#ifndef PERIPHERALS_USE_DELAY_US
# pragma info "Compiled without usecond delay."
#endif
#endif /* PERIPHERALS_CONFIG_HPP_ */

38
Inc/peripherals_io.hpp Normal file
View File

@ -0,0 +1,38 @@
/*
* IO.h
*
* Created on: Feb 24, 2021
* Author: erki
*/
#ifndef PERIPHERALS_IO_HPP_
#define PERIPHERALS_IO_HPP_
#include <peripherals_config.hpp>
#include <cstdint>
#include <gpio.h>
namespace Peripherals
{
struct IO
{
GPIO_TypeDef* port;
std::uint16_t pin;
IO() = default;
IO(GPIO_TypeDef* port, const unsigned short pin);
void Set(const bool state);
void Toggle();
bool Read();
#ifdef PERIPHERALS_USE_DELAY_US
void SetDelayUs(const bool state, const std::uint32_t micros);
#endif
};
} /* namespace Peripherals */
#endif /* PERIPHERALS_IO_HPP_ */

View File

@ -0,0 +1,54 @@
/*
* peripherals_motors.hpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#ifndef PERIPHERALS_MOTORS_HPP_
#define PERIPHERALS_MOTORS_HPP_
#include "peripherals_io.hpp"
#include <tim.h>
#include "peripherals_pwm_channel.hpp"
namespace Peripherals
{
class IMotors
{
public:
struct TwoChannelMotorData
{
PwmChannel forward;
PwmChannel backward;
};
virtual void Set(const std::int16_t left, const std::int16_t right) = 0;
virtual void Coast() = 0;
virtual void Break() = 0;
virtual void Unbreak() = 0;
};
class DualDrvMotors : public IMotors
{
public:
DualDrvMotors(const IMotors::TwoChannelMotorData& left, const IMotors::TwoChannelMotorData& right, const IO& sleep_pin);
virtual void Set(const std::int16_t left, const std::int16_t right) override;
virtual void Coast() override;
virtual void Break() override;
virtual void Unbreak() override;
private:
IMotors::TwoChannelMotorData _left;
IMotors::TwoChannelMotorData _right;
IO _sleep_pin;
};
}
#endif /* PERIPHERALS_MOTORS_HPP_ */

View File

@ -0,0 +1,44 @@
/*
* peripherals_pwm.hpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#ifndef PERIPHERALS_PWM_CHANNEL_HPP_
#define PERIPHERALS_PWM_CHANNEL_HPP_
#include <cstdint>
#include <tim.h>
#include "peripherals_io.hpp"
namespace Peripherals
{
struct PwmChannel
{
TIM_HandleTypeDef* timer;
std::uint32_t channel;
std::uint32_t timer_code;
IO pin;
PwmChannel() = default;
PwmChannel(TIM_HandleTypeDef* timer,
const std::uint32_t channel,
const std::uint32_t timer_code,
const IO& pin);
void PinToPwm();
void PinToGpio();
void Enable();
void Disable();
};
}
#endif /* PERIPHERALS_PWM_CHANNEL_HPP_ */

View File

@ -0,0 +1,38 @@
/*
* peripherals_utility.hpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#ifndef PERIPHERALS_UTILITY_HPP_
#define PERIPHERALS_UTILITY_HPP_
#include <cstdint>
#include "peripherals_config.hpp"
namespace Peripherals
{
void Initialize();
#ifdef PERIPHERALS_USE_DELAY_US
void DelayUs(const std::uint32_t micros);
#endif
template<typename T>
constexpr const T& Clamp(const T& v, const T& lo, const T& hi)
{
if (v > hi)
return hi;
else if (v < lo)
return lo;
else
return v;
}
}
#endif /* PERIPHERALS_UTILITY_HPP_ */

44
Src/peripherals_io.cpp Normal file
View File

@ -0,0 +1,44 @@
/*
* IO.cpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#include <peripherals_io.hpp>
#include "peripherals_utility.hpp"
namespace Peripherals
{
IO::IO(GPIO_TypeDef* port, const unsigned short pin)
: port(port)
, pin(std::uint16_t(pin))
{ }
void IO::Set(const bool state)
{
HAL_GPIO_WritePin(port, pin, GPIO_PinState(state));
}
void IO::Toggle()
{
HAL_GPIO_TogglePin(port, pin);
}
bool IO::Read()
{
return bool(HAL_GPIO_ReadPin(port, pin));
}
#ifdef PERIPHERALS_USE_DELAY_US
void IO::SetDelayUs(const bool state, const std::uint32_t micros)
{
HAL_GPIO_WritePin(port, pin, GPIO_PinState(state));
DelayUs(micros);
}
#endif
} /* namespace Peripherals */

View File

@ -0,0 +1,94 @@
/*
* peripherals_motors.cpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#include "peripherals_motors.hpp"
namespace Peripherals
{
DualDrvMotors::DualDrvMotors(const IMotors::TwoChannelMotorData& left,
const IMotors::TwoChannelMotorData& right, const IO& sleep_pin)
: _left(left)
, _right(right)
, _sleep_pin(sleep_pin)
{
_left.forward.Enable();
_left.backward.Enable();
_right.forward.Enable();
_right.backward.Enable();
Set(0, 0);
}
void DualDrvMotors::Set(const std::int16_t left, const std::int16_t right)
{
if (left > 0)
{
__HAL_TIM_SET_COMPARE(_left.forward.timer, _left.forward.channel, left);
__HAL_TIM_SET_COMPARE(_left.backward.timer, _left.backward.channel, 0);
}
else
{
__HAL_TIM_SET_COMPARE(_left.forward.timer, _left.forward.channel, 0);
__HAL_TIM_SET_COMPARE(_left.backward.timer, _left.backward.channel, (-1 * left));
}
if (right > 0)
{
__HAL_TIM_SET_COMPARE(_right.forward.timer, _right.forward.channel, right);
__HAL_TIM_SET_COMPARE(_right.backward.timer, _right.backward.channel, 0);
}
else
{
__HAL_TIM_SET_COMPARE(_right.forward.timer, _right.forward.channel, 0);
__HAL_TIM_SET_COMPARE(_right.backward.timer, _right.backward.channel, (-1 * right));
}
}
void DualDrvMotors::Coast()
{
__HAL_TIM_SET_COMPARE(_left.forward.timer, _left.forward.channel, 0);
__HAL_TIM_SET_COMPARE(_left.backward.timer, _left.backward.channel, 0);
__HAL_TIM_SET_COMPARE(_right.forward.timer, _right.forward.channel, 0);
__HAL_TIM_SET_COMPARE(_right.backward.timer, _right.backward.channel, 0);
}
void DualDrvMotors::Break()
{
Set(0, 0);
_left.forward.Disable();
_left.backward.Disable();
_right.forward.Disable();
_right.backward.Disable();
_left.forward.PinToGpio();
_left.backward.PinToGpio();
_right.forward.PinToGpio();
_right.backward.PinToGpio();
_left.forward.pin.Set(true);
_left.backward.pin.Set(true);
_right.forward.pin.Set(true);
_right.backward.pin.Set(true);
}
void DualDrvMotors::Unbreak()
{
_left.forward.PinToPwm();
_left.backward.PinToPwm();
_right.forward.PinToPwm();
_right.backward.PinToPwm();
_left.forward.Enable();
_left.backward.Enable();
_right.forward.Enable();
_right.backward.Enable();
}
}

View File

@ -0,0 +1,58 @@
/*
* peripherals_pwm_channel.cpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#include "peripherals_pwm_channel.hpp"
namespace Peripherals
{
PwmChannel::PwmChannel(TIM_HandleTypeDef* timer,
const std::uint32_t channel,
const std::uint32_t timer_code,
const IO& pin)
: timer(timer)
, channel(channel)
, timer_code(timer_code)
, pin(pin)
{ }
void PwmChannel::PinToPwm()
{
GPIO_InitTypeDef gpio_init = { 0 };
gpio_init.Pin = pin.pin;
gpio_init.Mode = GPIO_MODE_AF_PP;
gpio_init.Pull = GPIO_NOPULL;
gpio_init.Speed = GPIO_SPEED_FREQ_LOW;
gpio_init.Alternate = timer_code;
HAL_GPIO_Init(pin.port, &gpio_init);
}
void PwmChannel::PinToGpio()
{
GPIO_InitTypeDef gpio_config = { 0 };
gpio_config.Pin = pin.pin;
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
gpio_config.Pull = GPIO_NOPULL;
gpio_config.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(pin.port, &gpio_config);
}
void PwmChannel::Enable()
{
HAL_TIM_PWM_Start(timer, channel);
}
void PwmChannel::Disable()
{
HAL_TIM_PWM_Stop(timer, channel);
}
}

View File

@ -0,0 +1,34 @@
/*
* peripherals_utility.cpp
*
* Created on: Feb 24, 2021
* Author: erki
*/
#include "peripherals_utility.hpp"
#include "main.h"
namespace Peripherals
{
void Initialize()
{
#ifdef PERIPHERALS_USE_DELAY_US
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
#endif
}
#ifdef PERIPHERALS_USE_DELAY_US
void DelayUs(const std::uint32_t micros)
{
const std::uint32_t tick_start = DWT->CYCCNT;
const std::uint32_t ticks_delay = micros * (SystemCoreClock / 1'000'000);
while (DWT->CYCCNT - tick_start < ticks_delay);
}
#endif
}