| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @file DcMotor.cpp | |||
| 3 | * @brief DC motor controller | |||
| 4 | * | |||
| 5 | * @date Dec 22, 2018 | |||
| 6 | * @author Matthew Kennedy | |||
| 7 | */ | |||
| 8 | ||||
| 9 | #include "pch.h" | |||
| 10 | ||||
| 11 | #include "dc_motor.h" | |||
| 12 | ||||
| 13 | 12 | TwoPinDcMotor::TwoPinDcMotor(OutputPin& disablePin) | ||
| 14 | 12 | : m_disable(&disablePin) | ||
| 15 | { | |||
| 16 | 12 | disable("init"); | ||
| 17 | 12 | } | ||
| 18 | ||||
| 19 | 6 | void TwoPinDcMotor::configure(IPwm& enable, IPwm& dir1, IPwm& dir2, bool isInverted) { | ||
| 20 | 6 | m_enable = &enable; | ||
| 21 | 6 | m_dir1 = &dir1; | ||
| 22 | 6 | m_dir2 = &dir2; | ||
| 23 | 6 | m_isInverted = isInverted; | ||
| 24 | 6 | } | ||
| 25 | ||||
| 26 | 155 | void TwoPinDcMotor::enable() { | ||
| 27 |
1/2✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 155 times.
✗ Decision 'false' not taken.
|
155 | if (m_disable) { |
| 28 | 155 | m_disable->setValue(false); | ||
| 29 | } | |||
| 30 | ||||
| 31 | 155 | m_msg = nullptr; | ||
| 32 | 155 | } | ||
| 33 | ||||
| 34 | 65 | void TwoPinDcMotor::disable(const char *msg) { | ||
| 35 | 65 | m_msg = msg; | ||
| 36 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 65 times.
✗ Decision 'false' not taken.
|
65 | if (m_disable) { |
| 37 | 65 | m_disable->setValue(true); | ||
| 38 | } | |||
| 39 | ||||
| 40 | // Also set the duty to zero | |||
| 41 | 65 | set(0); | ||
| 42 | 65 | } | ||
| 43 | ||||
| 44 | ✗ | bool TwoPinDcMotor::isOpenDirection() const { | ||
| 45 | ✗ | return m_value >= 0; | ||
| 46 | } | |||
| 47 | ||||
| 48 | 531080 | float TwoPinDcMotor::get() const { | ||
| 49 | 531080 | return m_value; | ||
| 50 | } | |||
| 51 | ||||
| 52 | /** | |||
| 53 | * @param duty value between -1.0 and 1.0 | |||
| 54 | */ | |||
| 55 | 224 | bool TwoPinDcMotor::set(float duty) | ||
| 56 | { | |||
| 57 | 224 | m_value = duty; | ||
| 58 | ||||
| 59 | // For low voltage, voltageRatio will be >1 to boost duty so that motor current stays the same | |||
| 60 | // At high voltage, the inverse will be true to keep behavior always the same. | |||
| 61 |
1/1✓ Branch 2 taken 224 times.
|
224 | float voltageRatio = 14 / Sensor::get(SensorType::BatteryVoltage).value_or(14); | |
| 62 | 224 | duty *= voltageRatio; | ||
| 63 | ||||
| 64 | // If not init, don't try to set | |||
| 65 |
4/6✓ Branch 0 taken 210 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 210 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 210 times.
|
2/2✓ Decision 'true' taken 14 times.
✓ Decision 'false' taken 210 times.
|
224 | if (!m_dir1 || !m_dir2 || !m_enable) { |
| 66 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 14 times.
✗ Decision 'false' not taken.
|
14 | if (m_disable) { |
| 67 | 14 | m_disable->setValue(true); | ||
| 68 | } | |||
| 69 | ||||
| 70 | 14 | return false; | ||
| 71 | } | |||
| 72 | ||||
| 73 | 210 | bool isPositive = duty > 0; | ||
| 74 | ||||
| 75 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 54 times.
|
2/2✓ Decision 'true' taken 156 times.
✓ Decision 'false' taken 54 times.
|
210 | if (!isPositive) { |
| 76 | 156 | duty = -duty; | ||
| 77 | } | |||
| 78 | ||||
| 79 | // below here 'duty' is a not negative | |||
| 80 | ||||
| 81 | // Clamp to 100% | |||
| 82 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 210 times.
|
210 | if (duty > 1.0f) { |
| 83 | ✗ | duty = 1.0f; | ||
| 84 | } | |||
| 85 | // Disable for very small duty | |||
| 86 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 158 times.
|
2/2✓ Decision 'true' taken 52 times.
✓ Decision 'false' taken 158 times.
|
210 | else if (duty < 0.01f) |
| 87 | { | |||
| 88 | 52 | duty = 0.0f; | ||
| 89 | } | |||
| 90 | ||||
| 91 | // If we're in two pin mode, force 100%, else use this pin to PWM | |||
| 92 |
2/2✓ Branch 0 taken 208 times.
✓ Branch 1 taken 2 times.
|
210 | float enableDuty = m_type == ControlType::PwmEnablePin ? duty : 1; | |
| 93 | ||||
| 94 | // Direction pins get 100% duty unless we're in PwmDirectionPins mode | |||
| 95 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 208 times.
|
210 | float dirDuty = m_type == ControlType::PwmDirectionPins ? duty : 1; | |
| 96 | ||||
| 97 | 210 | m_enable->setSimplePwmDutyCycle(enableDuty); | ||
| 98 | 210 | float recipDuty = 0; | ||
| 99 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 210 times.
|
210 | if (m_isInverted) { |
| 100 | ✗ | dirDuty = 1.0f - dirDuty; | ||
| 101 | ✗ | recipDuty = 1.0f; | ||
| 102 | } | |||
| 103 | ||||
| 104 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 156 times.
|
210 | m_dir1->setSimplePwmDutyCycle(isPositive ? dirDuty : recipDuty); | |
| 105 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 156 times.
|
210 | m_dir2->setSimplePwmDutyCycle(isPositive ? recipDuty : dirDuty); | |
| 106 | ||||
| 107 | // This motor has no fault detection, so always return false (indicate success). | |||
| 108 | 210 | return false; | ||
| 109 | } | |||
| 110 |