File evamKickDecor.h¶
File List > src > evamKickDecor.h
Go to the documentation of this file
#pragma once
#include <Arduino.h>
#include <evaTickable.h>
using namespace eva;
namespace evam
{
constexpr unsigned short kDefaultKickDurationMs = 20;
constexpr signed short kDefaultKickPower = 1000;
constexpr signed short kMaxKickPower = 1000;
struct KickConfig {
unsigned short duration;
signed short power;
KickConfig(unsigned short duration, signed short power) : duration(duration > 0 ? duration : kDefaultKickDurationMs), power(constrain(power, 0, kMaxKickPower)) {}
};
template <class TMotor,
unsigned short tDefaultKickDurationMs = kDefaultKickDurationMs,
signed short tDefaultKickPower = kDefaultKickPower>
class KickDecor : public virtual Tickable, public TMotor
{
static_assert(tDefaultKickDurationMs > 0, "tDefaultKickDurationMs must be > 0");
static_assert(tDefaultKickPower > 0 && tDefaultKickPower <= kMaxKickPower, "tDefaultKickPower out of range");
private:
KickConfig mConfig;
signed short mTargetSpeed = 0;
unsigned long mHoldingStartedAt = 0;
signed short calculateKickPower(signed short aValue) const
{
if ((mTargetSpeed <= 0) && (aValue > 0))
return mConfig.power;
if ((mTargetSpeed >= 0) && (aValue < 0))
return -mConfig.power;
return 0;
}
void tick() override
{
if (!mHoldingStartedAt)
return;
if (millis() - mHoldingStartedAt < mConfig.duration)
return;
TMotor::Go(mTargetSpeed);
mHoldingStartedAt = 0;
}
public:
KickDecor() : mConfig(tDefaultKickDurationMs, tDefaultKickPower) {}
template<typename... Args>
KickDecor(KickConfig config, Args... args) : mConfig(config), TMotor(args...) {}
void SetupKickstart(unsigned short duration, signed short power)
{
SetKickDuration(duration);
SetKickPower(power);
}
void SetKickDuration(unsigned short aValue)
{
if (aValue > 0)
mConfig.duration = aValue;
}
unsigned short GetKickDuration() const
{
return mConfig.duration;
}
void SetKickPower(signed short aValue)
{
mConfig.power = constrain(aValue, 0, 1000);
}
signed short GetKickPower() const
{
return mConfig.power;
}
void Go(signed short aValue)
{
signed short needKick = calculateKickPower(aValue);
mTargetSpeed = aValue;
if (needKick)
{
TMotor::Go(needKick);
mHoldingStartedAt = millis();
return;
}
if (mHoldingStartedAt)
return;
TMotor::Go(aValue);
}
};
}