Jon Freeman / Mbed 2 deprecated Alternator2020_06

Dependencies:   mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM

Committer:
JonFreeman
Date:
Sat Dec 05 12:40:17 2020 +0000
Revision:
5:6ca3e7ffc553
Parent:
3:43cb067ecd00
Code for 'Smart Regulator' to August 2020, published as is. Basic low-level functions all thoroughly tested and debugged, top level algorithms have scope for further development - over to you! For help contact jon @ jons-workshop[.com

Who changed what in which revision?

UserRevisionLine numberNew 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 5:6ca3e7ffc553 21 Set_Speed_Lever (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 5:6ca3e7ffc553 78 void Engine_Manager::Set_Speed_Lever (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 5:6ca3e7ffc553 94 Set_Speed_Lever (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 5:6ca3e7ffc553 100 Set_Speed_Lever (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 5:6ca3e7ffc553 151 Set_Speed_Lever (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