Default mbed pwm doesn't have enough resolution at high frequencies, thats why I implemented VNH5019 Motor carrier with FastPWM.
Fork of VNH5019 by
VNH5019Accel.h@14:193c422498bf, 2018-04-10 (annotated)
- Committer:
- mbedoguz
- Date:
- Tue Apr 10 21:30:47 2018 +0000
- Revision:
- 14:193c422498bf
- Parent:
- 5:b5f360a16354
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ianmcc | 5:b5f360a16354 | 1 | // VNH5015 driver with acceleration control |
ianmcc | 5:b5f360a16354 | 2 | // A drop-in replacement for the basic VNH5019 |
ianmcc | 5:b5f360a16354 | 3 | |
ianmcc | 5:b5f360a16354 | 4 | #if !defined(VNH5019ACCEL_H) |
ianmcc | 5:b5f360a16354 | 5 | #define VNH5019ACCEL_H |
ianmcc | 5:b5f360a16354 | 6 | |
ianmcc | 5:b5f360a16354 | 7 | #include "VNH5019.h" |
ianmcc | 5:b5f360a16354 | 8 | #include <Ticker.h> |
ianmcc | 5:b5f360a16354 | 9 | |
ianmcc | 5:b5f360a16354 | 10 | // The maximum acceleration, in fractions of full speed per second |
ianmcc | 5:b5f360a16354 | 11 | float const VNH5019MaxAccel = 4; |
ianmcc | 5:b5f360a16354 | 12 | |
ianmcc | 5:b5f360a16354 | 13 | // Tick period in microseconds for updating the speed |
ianmcc | 5:b5f360a16354 | 14 | int const VNH5019Tick_us = 20000; |
ianmcc | 5:b5f360a16354 | 15 | |
ianmcc | 5:b5f360a16354 | 16 | float const VNH5019ChangePerTick = VNH5019MaxAccel * VNH5019Tick_us / 1000000; |
ianmcc | 5:b5f360a16354 | 17 | |
ianmcc | 5:b5f360a16354 | 18 | // allow braking to come on faster |
ianmcc | 5:b5f360a16354 | 19 | float const VNH5019BrakeChangePerTick = VNH5019ChangePerTick*10; |
ianmcc | 5:b5f360a16354 | 20 | |
ianmcc | 5:b5f360a16354 | 21 | class VNH5019Accel |
ianmcc | 5:b5f360a16354 | 22 | { |
ianmcc | 5:b5f360a16354 | 23 | public: |
ianmcc | 5:b5f360a16354 | 24 | VNH5019Accel(PinName INA_, PinName INB_, PinName ENDIAG_, PinName CS_, PinName PWM_) |
ianmcc | 5:b5f360a16354 | 25 | : Driver(INA_, INB_, ENDIAG_, CS_, PWM_), |
ianmcc | 5:b5f360a16354 | 26 | CurrentSpeed(0.0), |
ianmcc | 5:b5f360a16354 | 27 | CurrentBrake(0.0), |
ianmcc | 5:b5f360a16354 | 28 | RequestedSpeed(0.0), |
ianmcc | 5:b5f360a16354 | 29 | RequestedBrake(0.0) |
ianmcc | 5:b5f360a16354 | 30 | { |
ianmcc | 5:b5f360a16354 | 31 | timer.attach_us(this, &VNH5019Accel::Interrupt, VNH5019Tick_us); |
ianmcc | 5:b5f360a16354 | 32 | } |
ianmcc | 5:b5f360a16354 | 33 | |
ianmcc | 5:b5f360a16354 | 34 | // set motor speed from -1.0 to +1.0 |
ianmcc | 5:b5f360a16354 | 35 | void speed(float Speed) |
ianmcc | 5:b5f360a16354 | 36 | { |
ianmcc | 5:b5f360a16354 | 37 | if (Speed < -1.0) |
ianmcc | 5:b5f360a16354 | 38 | Speed = 1.0; |
ianmcc | 5:b5f360a16354 | 39 | else if (Speed > 1.0) |
ianmcc | 5:b5f360a16354 | 40 | Speed = 1.0; |
ianmcc | 5:b5f360a16354 | 41 | RequestedSpeed = Speed; |
ianmcc | 5:b5f360a16354 | 42 | } |
ianmcc | 5:b5f360a16354 | 43 | |
ianmcc | 5:b5f360a16354 | 44 | // stop (no current to the motors) |
ianmcc | 5:b5f360a16354 | 45 | void stop() |
ianmcc | 5:b5f360a16354 | 46 | { |
ianmcc | 5:b5f360a16354 | 47 | RequestedSpeed = 0.0; |
ianmcc | 5:b5f360a16354 | 48 | } |
ianmcc | 5:b5f360a16354 | 49 | |
ianmcc | 5:b5f360a16354 | 50 | // Brake, with strength 0..1 |
ianmcc | 5:b5f360a16354 | 51 | void brake(float Brake) |
ianmcc | 5:b5f360a16354 | 52 | { |
ianmcc | 5:b5f360a16354 | 53 | if (Brake < 0.0) |
ianmcc | 5:b5f360a16354 | 54 | Brake = 0; |
ianmcc | 5:b5f360a16354 | 55 | else if (Brake > 1.0) |
ianmcc | 5:b5f360a16354 | 56 | Brake = 1.0; |
ianmcc | 5:b5f360a16354 | 57 | RequestedBrake = Brake; |
ianmcc | 5:b5f360a16354 | 58 | RequestedSpeed = 0.0; |
ianmcc | 5:b5f360a16354 | 59 | } |
ianmcc | 5:b5f360a16354 | 60 | |
ianmcc | 5:b5f360a16354 | 61 | // returns the current through the motor, in mA |
ianmcc | 5:b5f360a16354 | 62 | float get_current_mA() |
ianmcc | 5:b5f360a16354 | 63 | { |
ianmcc | 5:b5f360a16354 | 64 | return Driver.get_current_mA(); |
ianmcc | 5:b5f360a16354 | 65 | } |
ianmcc | 5:b5f360a16354 | 66 | |
ianmcc | 5:b5f360a16354 | 67 | // returns true if there has been a fault |
ianmcc | 5:b5f360a16354 | 68 | bool is_fault() |
ianmcc | 5:b5f360a16354 | 69 | { |
ianmcc | 5:b5f360a16354 | 70 | return Driver.is_fault(); |
ianmcc | 5:b5f360a16354 | 71 | } |
ianmcc | 5:b5f360a16354 | 72 | |
ianmcc | 5:b5f360a16354 | 73 | // Clears the fault condition |
ianmcc | 5:b5f360a16354 | 74 | // PRECONDITION: is_fault() |
ianmcc | 5:b5f360a16354 | 75 | void clear_fault() |
ianmcc | 5:b5f360a16354 | 76 | { |
ianmcc | 5:b5f360a16354 | 77 | timer.detach(); |
ianmcc | 5:b5f360a16354 | 78 | Driver.clear_fault(); |
ianmcc | 5:b5f360a16354 | 79 | timer.attach_us(this, &VNH5019Accel::Interrupt, VNH5019Tick_us); |
ianmcc | 5:b5f360a16354 | 80 | } |
ianmcc | 5:b5f360a16354 | 81 | |
ianmcc | 5:b5f360a16354 | 82 | // disable the motor, and set outputs to zero. This is a low power mode. |
ianmcc | 5:b5f360a16354 | 83 | void disable() |
ianmcc | 5:b5f360a16354 | 84 | { |
ianmcc | 5:b5f360a16354 | 85 | timer.detach(); |
ianmcc | 5:b5f360a16354 | 86 | Driver.disable(); |
ianmcc | 5:b5f360a16354 | 87 | } |
ianmcc | 5:b5f360a16354 | 88 | |
ianmcc | 5:b5f360a16354 | 89 | // enable the motor. |
ianmcc | 5:b5f360a16354 | 90 | void enable() |
ianmcc | 5:b5f360a16354 | 91 | { |
ianmcc | 5:b5f360a16354 | 92 | timer.detach(); |
ianmcc | 5:b5f360a16354 | 93 | Driver.enable(); |
ianmcc | 5:b5f360a16354 | 94 | timer.attach_us(this, &VNH5019Accel::Interrupt, VNH5019Tick_us); |
ianmcc | 5:b5f360a16354 | 95 | } |
ianmcc | 5:b5f360a16354 | 96 | |
ianmcc | 5:b5f360a16354 | 97 | // set the PWM period of oscillation in seconds |
ianmcc | 5:b5f360a16354 | 98 | void set_pwm_period(float p) |
ianmcc | 5:b5f360a16354 | 99 | { |
ianmcc | 5:b5f360a16354 | 100 | Driver.set_pwm_period(p); |
ianmcc | 5:b5f360a16354 | 101 | } |
ianmcc | 5:b5f360a16354 | 102 | |
ianmcc | 5:b5f360a16354 | 103 | private: |
ianmcc | 5:b5f360a16354 | 104 | VNH5019 Driver; |
ianmcc | 5:b5f360a16354 | 105 | Ticker timer; |
ianmcc | 5:b5f360a16354 | 106 | float CurrentSpeed; // this is only ever accessed from the ISR, so no need for volatile |
ianmcc | 5:b5f360a16354 | 107 | float CurrentBrake; |
ianmcc | 5:b5f360a16354 | 108 | volatile float RequestedSpeed; |
ianmcc | 5:b5f360a16354 | 109 | volatile float RequestedBrake; |
ianmcc | 5:b5f360a16354 | 110 | void Interrupt(); |
ianmcc | 5:b5f360a16354 | 111 | }; |
ianmcc | 5:b5f360a16354 | 112 | |
ianmcc | 5:b5f360a16354 | 113 | // Helper class for the Pololu dual VNH5019 motor shield. |
ianmcc | 5:b5f360a16354 | 114 | // The default constructor uses the default arduino pins. |
ianmcc | 5:b5f360a16354 | 115 | // The motors can be accessed either by .m1 or .m2, or by operator()(i) where i is 1 or 2. |
ianmcc | 5:b5f360a16354 | 116 | class DualVNH5019AccelMotorShield |
ianmcc | 5:b5f360a16354 | 117 | { |
ianmcc | 5:b5f360a16354 | 118 | public: |
ianmcc | 5:b5f360a16354 | 119 | // default pin selection |
ianmcc | 5:b5f360a16354 | 120 | DualVNH5019AccelMotorShield(); // Default pin selection. |
ianmcc | 5:b5f360a16354 | 121 | |
ianmcc | 5:b5f360a16354 | 122 | // User-defined pin selection. |
ianmcc | 5:b5f360a16354 | 123 | DualVNH5019AccelMotorShield(PinName INA1_, PinName INB1_, PinName ENDIAG1_, PinName CS1_, PinName PWM1_, |
ianmcc | 5:b5f360a16354 | 124 | PinName INA2_, PinName INB2_, PinName ENDIAG2_, PinName CS2_, PinName PWM2_) |
ianmcc | 5:b5f360a16354 | 125 | : m1(INA1_, INB1_, ENDIAG1_, CS1_, PWM1_), |
ianmcc | 5:b5f360a16354 | 126 | m2(INA2_, INB2_, ENDIAG2_, CS2_, PWM2_) |
ianmcc | 5:b5f360a16354 | 127 | { |
ianmcc | 5:b5f360a16354 | 128 | } |
ianmcc | 5:b5f360a16354 | 129 | |
ianmcc | 5:b5f360a16354 | 130 | // returns the given motor object, 1 or 2. |
ianmcc | 5:b5f360a16354 | 131 | VNH5019Accel& operator()(int m) |
ianmcc | 5:b5f360a16354 | 132 | { |
ianmcc | 5:b5f360a16354 | 133 | return m == 1 ? m1 : m2; |
ianmcc | 5:b5f360a16354 | 134 | } |
ianmcc | 5:b5f360a16354 | 135 | |
ianmcc | 5:b5f360a16354 | 136 | VNH5019Accel m1; |
ianmcc | 5:b5f360a16354 | 137 | VNH5019Accel m2; |
ianmcc | 5:b5f360a16354 | 138 | }; |
ianmcc | 5:b5f360a16354 | 139 | |
ianmcc | 5:b5f360a16354 | 140 | #endif |