Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM
rpm.cpp@3:43cb067ecd00, 2020-07-27 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Jul 27 08:44:59 2020 +0000
- Revision:
- 3:43cb067ecd00
- Child:
- 5:6ca3e7ffc553
End of July after good day out at Ashton Court
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| JonFreeman | 3:43cb067ecd00 | 1 | #include "mbed.h" |
| JonFreeman | 3:43cb067ecd00 | 2 | #include "rpm.h" |
| JonFreeman | 3:43cb067ecd00 | 3 | #include "Alternator.h" |
| JonFreeman | 3:43cb067ecd00 | 4 | //#include "BufferedSerial.h" |
| JonFreeman | 3:43cb067ecd00 | 5 | //extern BufferedSerial pc; |
| JonFreeman | 3:43cb067ecd00 | 6 | extern ee_settings_2020 user_settings; |
| JonFreeman | 3:43cb067ecd00 | 7 | |
| JonFreeman | 3:43cb067ecd00 | 8 | Engine_Manager::Engine_Manager (PinName ms, PinName cm, PinName for_servo) : MagnetoSignal(ms), CleanedMagneto(cm), Speed_ControlServo(for_servo) |
| JonFreeman | 3:43cb067ecd00 | 9 | { |
| JonFreeman | 3:43cb067ecd00 | 10 | // Constructor |
| JonFreeman | 3:43cb067ecd00 | 11 | magneto_stretch = false; |
| JonFreeman | 3:43cb067ecd00 | 12 | rpm_in_run_range = false; |
| JonFreeman | 3:43cb067ecd00 | 13 | latest_RPM_reading = core_call_count = 0; |
| JonFreeman | 3:43cb067ecd00 | 14 | last_update_time = 0; |
| JonFreeman | 3:43cb067ecd00 | 15 | filtered_measured_RPM = requested_RPM = 0.0; |
| JonFreeman | 3:43cb067ecd00 | 16 | MagnetoSignal.rise (callback(this, &Engine_Manager::MagRise)); // Attach handler to the rising interruptIn edge |
| JonFreeman | 3:43cb067ecd00 | 17 | MagnetoSignal.fall (callback(this, &Engine_Manager::MagFall)); // Attach handler to the rising interruptIn edge |
| JonFreeman | 3:43cb067ecd00 | 18 | // microsecs.reset () ; // timer = 0 |
| JonFreeman | 3:43cb067ecd00 | 19 | // microsecs.start () ; // 64 bit, counts micro seconds and times out in half million years |
| JonFreeman | 3:43cb067ecd00 | 20 | servo_position = MIN_WORKING_THROTTLE; |
| JonFreeman | 3:43cb067ecd00 | 21 | Speed_Control (MIN_WORKING_THROTTLE); |
| JonFreeman | 3:43cb067ecd00 | 22 | }; |
| JonFreeman | 3:43cb067ecd00 | 23 | |
| JonFreeman | 3:43cb067ecd00 | 24 | void Engine_Manager::magneto_timeoutC () |
| JonFreeman | 3:43cb067ecd00 | 25 | { |
| JonFreeman | 3:43cb067ecd00 | 26 | magneto_stretch = false; // Magneto ringing finished by now, re-enable magneto pulse count |
| JonFreeman | 3:43cb067ecd00 | 27 | CleanedMagneto = 0; // Cleaned tacho output brought out to pin to look at with scope |
| JonFreeman | 3:43cb067ecd00 | 28 | } |
| JonFreeman | 3:43cb067ecd00 | 29 | |
| JonFreeman | 3:43cb067ecd00 | 30 | void Engine_Manager::MagRise () |
| JonFreeman | 3:43cb067ecd00 | 31 | { |
| JonFreeman | 3:43cb067ecd00 | 32 | if (!magneto_stretch) { // May get this interrupt more than once per magneto pulse, respond to first, lock out subsequent |
| JonFreeman | 3:43cb067ecd00 | 33 | // until magneto_timeout time has elapsed |
| JonFreeman | 3:43cb067ecd00 | 34 | magneto_stretch = true; // Set flag preventing repeat interrupts until after Timeout interrupt handler clears it 5ms later |
| JonFreeman | 3:43cb067ecd00 | 35 | new_time = microsecs.read_high_resolution_us(); |
| JonFreeman | 3:43cb067ecd00 | 36 | magt0 = new_time - magt1; // microsecs between most recent two sparks |
| JonFreeman | 3:43cb067ecd00 | 37 | magt1 = new_time; // actual time microsecs of most recent spark |
| JonFreeman | 3:43cb067ecd00 | 38 | magneto_timoC.attach_us (callback(this, &Engine_Manager::magneto_timeoutC), DEBOUNCE_US); // To ignore ringing and multiple counts on magneto output, all settled within about 5ms |
| JonFreeman | 3:43cb067ecd00 | 39 | CleanedMagneto = 1; // Cleaned tacho output brought out to pin to look at with scope |
| JonFreeman | 3:43cb067ecd00 | 40 | } |
| JonFreeman | 3:43cb067ecd00 | 41 | } |
| JonFreeman | 3:43cb067ecd00 | 42 | |
| JonFreeman | 3:43cb067ecd00 | 43 | void Engine_Manager::MagFall () // Need only rising or falling edge, not both |
| JonFreeman | 3:43cb067ecd00 | 44 | { |
| JonFreeman | 3:43cb067ecd00 | 45 | } |
| JonFreeman | 3:43cb067ecd00 | 46 | |
| JonFreeman | 3:43cb067ecd00 | 47 | void Engine_Manager::RPM_update () |
| JonFreeman | 3:43cb067ecd00 | 48 | { |
| JonFreeman | 3:43cb067ecd00 | 49 | last_update_time = microsecs.read_high_resolution_us(); |
| JonFreeman | 3:43cb067ecd00 | 50 | time_since_last_spark = last_update_time - magt1; |
| JonFreeman | 3:43cb067ecd00 | 51 | if (time_since_last_spark > 500000) { // engine probably not running |
| JonFreeman | 3:43cb067ecd00 | 52 | latest_RPM_reading = 0; |
| JonFreeman | 3:43cb067ecd00 | 53 | running_flag = false; |
| JonFreeman | 3:43cb067ecd00 | 54 | } |
| JonFreeman | 3:43cb067ecd00 | 55 | else { |
| JonFreeman | 3:43cb067ecd00 | 56 | running_flag = true; |
| JonFreeman | 3:43cb067ecd00 | 57 | latest_RPM_reading = (60000000 / magt0); |
| JonFreeman | 3:43cb067ecd00 | 58 | } |
| JonFreeman | 3:43cb067ecd00 | 59 | filtered_measured_RPM *= (1.0 - RPM_FILTER_FACTOR); |
| JonFreeman | 3:43cb067ecd00 | 60 | filtered_measured_RPM += RPM_FILTER_FACTOR * (double)latest_RPM_reading; |
| JonFreeman | 3:43cb067ecd00 | 61 | } |
| JonFreeman | 3:43cb067ecd00 | 62 | |
| JonFreeman | 3:43cb067ecd00 | 63 | bool Engine_Manager::running () // Answers question is engine running? |
| JonFreeman | 3:43cb067ecd00 | 64 | { |
| JonFreeman | 3:43cb067ecd00 | 65 | return running_flag; |
| JonFreeman | 3:43cb067ecd00 | 66 | } |
| JonFreeman | 3:43cb067ecd00 | 67 | |
| JonFreeman | 3:43cb067ecd00 | 68 | uint32_t Engine_Manager::RPM_latest () |
| JonFreeman | 3:43cb067ecd00 | 69 | { |
| JonFreeman | 3:43cb067ecd00 | 70 | return latest_RPM_reading; |
| JonFreeman | 3:43cb067ecd00 | 71 | } |
| JonFreeman | 3:43cb067ecd00 | 72 | |
| JonFreeman | 3:43cb067ecd00 | 73 | uint32_t Engine_Manager::RPM_filtered () |
| JonFreeman | 3:43cb067ecd00 | 74 | { |
| JonFreeman | 3:43cb067ecd00 | 75 | return (uint32_t)filtered_measured_RPM; |
| JonFreeman | 3:43cb067ecd00 | 76 | } |
| JonFreeman | 3:43cb067ecd00 | 77 | |
| JonFreeman | 3:43cb067ecd00 | 78 | void Engine_Manager::Speed_Control (double th) // Make this private once all throttle refs local |
| JonFreeman | 3:43cb067ecd00 | 79 | { |
| JonFreeman | 3:43cb067ecd00 | 80 | if (user_settings.rd(SERVO_DIR) == 0) |
| JonFreeman | 3:43cb067ecd00 | 81 | Speed_ControlServo = th; |
| JonFreeman | 3:43cb067ecd00 | 82 | else |
| JonFreeman | 3:43cb067ecd00 | 83 | Speed_ControlServo = 1.0 - th; |
| JonFreeman | 3:43cb067ecd00 | 84 | } |
| JonFreeman | 3:43cb067ecd00 | 85 | |
| JonFreeman | 3:43cb067ecd00 | 86 | uint32_t Engine_Manager::set_RPM_literal (uint32_t new_rpm) // Returns latest measured RPM |
| JonFreeman | 3:43cb067ecd00 | 87 | { |
| JonFreeman | 3:43cb067ecd00 | 88 | if (new_rpm > MAX_RPM) |
| JonFreeman | 3:43cb067ecd00 | 89 | new_rpm = MAX_RPM; |
| JonFreeman | 3:43cb067ecd00 | 90 | if (new_rpm >= MIN_RPM) { // Runnable or make runnable |
| JonFreeman | 3:43cb067ecd00 | 91 | if (!rpm_in_run_range) { // Transition from idle to working revs |
| JonFreeman | 3:43cb067ecd00 | 92 | rpm_in_run_range = true; |
| JonFreeman | 3:43cb067ecd00 | 93 | servo_position = MIN_WORKING_THROTTLE; // set throttle to probably somewhere near low useful revs |
| JonFreeman | 3:43cb067ecd00 | 94 | Speed_Control (MIN_WORKING_THROTTLE); |
| JonFreeman | 3:43cb067ecd00 | 95 | } // Endof transition from idle to working revs |
| JonFreeman | 3:43cb067ecd00 | 96 | } // Endof Runnable or make runnable |
| JonFreeman | 3:43cb067ecd00 | 97 | else { // requested rpm are below useful, so kill engine |
| JonFreeman | 3:43cb067ecd00 | 98 | if (rpm_in_run_range) { // detect transition from useful work to idle |
| JonFreeman | 3:43cb067ecd00 | 99 | servo_position = 0.0; |
| JonFreeman | 3:43cb067ecd00 | 100 | Speed_Control (0.0); |
| JonFreeman | 3:43cb067ecd00 | 101 | rpm_in_run_range = false; |
| JonFreeman | 3:43cb067ecd00 | 102 | } |
| JonFreeman | 3:43cb067ecd00 | 103 | } |
| JonFreeman | 3:43cb067ecd00 | 104 | requested_RPM = (double) new_rpm; |
| JonFreeman | 3:43cb067ecd00 | 105 | return latest_RPM_reading; |
| JonFreeman | 3:43cb067ecd00 | 106 | } |
| JonFreeman | 3:43cb067ecd00 | 107 | |
| JonFreeman | 3:43cb067ecd00 | 108 | uint32_t Engine_Manager::set_RPM_percent (uint32_t new_percent) |
| JonFreeman | 3:43cb067ecd00 | 109 | { // Returns latest measured RPM |
| JonFreeman | 3:43cb067ecd00 | 110 | uint32_t temp = 0; |
| JonFreeman | 3:43cb067ecd00 | 111 | if (new_percent > 100) new_percent = 100; |
| JonFreeman | 3:43cb067ecd00 | 112 | if (new_percent != 0) |
| JonFreeman | 3:43cb067ecd00 | 113 | temp = MIN_RPM + (((MAX_RPM - MIN_RPM) * new_percent) / 100); |
| JonFreeman | 3:43cb067ecd00 | 114 | return set_RPM_literal (temp); |
| JonFreeman | 3:43cb067ecd00 | 115 | } |
| JonFreeman | 3:43cb067ecd00 | 116 | |
| JonFreeman | 3:43cb067ecd00 | 117 | uint32_t Engine_Manager::RPM_percent_to_actual (uint32_t new_percent) |
| JonFreeman | 3:43cb067ecd00 | 118 | { // Returns RPM percentage converted to actual RPM |
| JonFreeman | 3:43cb067ecd00 | 119 | uint32_t temp = 0; |
| JonFreeman | 3:43cb067ecd00 | 120 | if (new_percent > 100) new_percent = 100; |
| JonFreeman | 3:43cb067ecd00 | 121 | if (new_percent != 0) |
| JonFreeman | 3:43cb067ecd00 | 122 | temp = MIN_RPM + (((MAX_RPM - MIN_RPM) * new_percent) / 100); |
| JonFreeman | 3:43cb067ecd00 | 123 | return temp; |
| JonFreeman | 3:43cb067ecd00 | 124 | } |
| JonFreeman | 3:43cb067ecd00 | 125 | |
| JonFreeman | 3:43cb067ecd00 | 126 | uint32_t Engine_Manager::get_RPM_requested () // Returns latest requested RPM |
| JonFreeman | 3:43cb067ecd00 | 127 | { |
| JonFreeman | 3:43cb067ecd00 | 128 | return (uint32_t) requested_RPM; |
| JonFreeman | 3:43cb067ecd00 | 129 | } |
| JonFreeman | 3:43cb067ecd00 | 130 | |
| JonFreeman | 3:43cb067ecd00 | 131 | double Engine_Manager::get_servo_position () // Only call from test printf in main |
| JonFreeman | 3:43cb067ecd00 | 132 | { |
| JonFreeman | 3:43cb067ecd00 | 133 | return servo_position; |
| JonFreeman | 3:43cb067ecd00 | 134 | } |
| JonFreeman | 3:43cb067ecd00 | 135 | |
| JonFreeman | 3:43cb067ecd00 | 136 | void Engine_Manager::manager_core() // Call this at 100 Hz |
| JonFreeman | 3:43cb067ecd00 | 137 | { |
| JonFreeman | 3:43cb067ecd00 | 138 | uint32_t i = ++core_call_count; |
| JonFreeman | 3:43cb067ecd00 | 139 | int32_t rpm_error; // signed |
| JonFreeman | 3:43cb067ecd00 | 140 | RPM_update (); // Updates filtered and unfiltered RPM measured, 100 times per sec |
| JonFreeman | 3:43cb067ecd00 | 141 | i &= 7; |
| JonFreeman | 3:43cb067ecd00 | 142 | switch (i) { |
| JonFreeman | 3:43cb067ecd00 | 143 | case 1: // Doing this at 12.5 Hz |
| JonFreeman | 3:43cb067ecd00 | 144 | rpm_error = filtered_measured_RPM - requested_RPM; // all doubles. Speed error is positive |
| JonFreeman | 3:43cb067ecd00 | 145 | if (rpm_in_run_range && (abs(rpm_error) > RPM_DEADBAND)) { // Try to adjust speed if not within margin |
| JonFreeman | 3:43cb067ecd00 | 146 | servo_position -= rpm_error / RPM_ERR_DENOM; //Denominator sets gain, the 'P', Proportional as in PID |
| JonFreeman | 3:43cb067ecd00 | 147 | if (servo_position < MIN_WORKING_THROTTLE) // Keep servo_position within limits |
| JonFreeman | 3:43cb067ecd00 | 148 | servo_position = MIN_WORKING_THROTTLE; |
| JonFreeman | 3:43cb067ecd00 | 149 | if (servo_position > MAX_WORKING_THROTTLE) |
| JonFreeman | 3:43cb067ecd00 | 150 | servo_position = MAX_WORKING_THROTTLE; |
| JonFreeman | 3:43cb067ecd00 | 151 | Speed_Control (servo_position); // Update signal to engine throttle control servo |
| JonFreeman | 3:43cb067ecd00 | 152 | } |
| JonFreeman | 3:43cb067ecd00 | 153 | break; |
| JonFreeman | 3:43cb067ecd00 | 154 | default: |
| JonFreeman | 3:43cb067ecd00 | 155 | break; |
| JonFreeman | 3:43cb067ecd00 | 156 | } |
| JonFreeman | 3:43cb067ecd00 | 157 | } |
| JonFreeman | 3:43cb067ecd00 | 158 | |
| JonFreeman | 3:43cb067ecd00 | 159 | |
| JonFreeman | 3:43cb067ecd00 | 160 | |
| JonFreeman | 3:43cb067ecd00 | 161 |