Code for 'Smart Regulator' featured in 'Model Engineer', November 2020 on. Contains all work to August 2020 including all code described. Top level algorithm development is quite spares, leaving some work for you! Any questions - jon@jons-workshop.com
Dependencies: mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM
Revision 5:6ca3e7ffc553, committed 2020-12-05
- Comitter:
- JonFreeman
- Date:
- Sat Dec 05 12:40:17 2020 +0000
- Parent:
- 4:28cc0cf01570
- Commit message:
- 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
Changed in this revision
--- a/Alternator.h Fri Aug 07 13:06:03 2020 +0000 +++ b/Alternator.h Sat Dec 05 12:40:17 2020 +0000 @@ -1,5 +1,8 @@ +/******************************************************************************* + DON'T FORGET TO REMOVE SOLDER LINKS SB16 AND SB18 ON L432KC BOARD +*******************************************************************************/ -#define GPS_ // Not the crap one I tried! +//#define GPS_ // Not the crap one I tried! const double ALTERNATOR_DESIGN_VOLTAGE = 14.0; // Used to scale down max field pwm when available voltage higher than this const double DRIVER_NEUTRAL = 0.18; // Proportion of driver's pot travel deemed to be zero power request
--- a/Servo.lib Fri Aug 07 13:06:03 2020 +0000 +++ b/Servo.lib Sat Dec 05 12:40:17 2020 +0000 @@ -1,1 +1,1 @@ -https://os.mbed.com/users/simon/code/Servo/#94980819591d +https://os.mbed.com/users/JonFreeman/code/Servo2/#94980819591d
--- a/cli.cpp Fri Aug 07 13:06:03 2020 +0000 +++ b/cli.cpp Sat Dec 05 12:40:17 2020 +0000 @@ -20,6 +20,8 @@ extern double Read_Link_Volts () ; extern double Read_Field_Volts () ; extern double Read_Ammeter () ; +extern void charge_pump_override (parameters & a) ; // 0 disables, !0 enables charge pump +extern void set_v_out_opamp (parameters & a) ; // 0 to 1.0 sets opamp output in range 0 to 5v, charge pump permitting //bool ee_settings_2020::wr (char c, uint32_t i) { // Write one setup char value to private buffer 'settings' /* @@ -264,6 +266,8 @@ struct kb_command const command_list[] = { {"?", "Lists available commands, same as ls", menucmd}, + {"cp", "Charge pump disable (0), enable (!0)", charge_pump_override}, + {"vo", "Set out volts to ESC 0 - 100 pct", set_v_out_opamp}, {"ft", "Test Field.set_for_speed fn", test_Fsfs_cmd}, {"at", "Initiate Auto Test sequence", auto_test_kickoff_cmd}, {"svod", "Set servo sense 0 or 1", servodir_cmd},
--- a/main.cpp Fri Aug 07 13:06:03 2020 +0000 +++ b/main.cpp Sat Dec 05 12:40:17 2020 +0000 @@ -1,3 +1,6 @@ +/******************************************************************************* + DON'T FORGET TO REMOVE SOLDER LINKS SB16 AND SB18 ON NUCLEO-L432KC BOARD +*******************************************************************************/ #include "mbed.h" #include "Alternator.h" #include "BufferedSerial.h" @@ -6,6 +9,7 @@ #include "rpm.h" #include "field.h" #include "gps_mod.h" + //#include "baro.h" #ifdef TARGET_NUCLEO_L432KC // 24LC and LM75 work @@ -97,7 +101,7 @@ 10 N.C. 11 N.C. 12 PA_8 D9 InterruptIn pulse_tacho from engine magneto, used to measure rpm -13 PA_11 D10 Speed_Control servo +13 PA_11 D10 Servo 14 PB_5 D11 NEW June 2019 - Output engine tacho cleaned-up, brought out to testpoint 4 NOT REALLY USEFUL 15 PB_4 D12 Scope_probe NOT REALLY USEFUL 16 PB_3 D13 LED Onboard LED @@ -173,6 +177,8 @@ bool auto_test_flag = false; +bool charge_pump_enable = true; + enum {SAFE_NOTHING, POT_SERVO_DIRECT, VARIABLE_VOLTAGE, FIXED_VOLTAGE, ENG_REVS_CTRL, POT_SETS_ENGINE_RPM, CURRENT_FEEDBACK_CTRL, AUTO_TEST} ; /* End of Global variable declarations */ @@ -180,7 +186,8 @@ void ISR_fast_interrupt () { static uint32_t t = 0, u25 = 0; Scope_probe = 1; // To show how much time spent in interrupt handler - CHARGE_PUMP = !CHARGE_PUMP; + if (charge_pump_enable) + CHARGE_PUMP = !CHARGE_PUMP; switch (t) { case 0: // Alternator output voltage flag_link_V_rd = true; @@ -240,7 +247,8 @@ double Read_Field_Volts () { - return field_volt_reading * 42.85; // divisor fiddled to make voltage reading correct ! +// return field_volt_reading * 42.85; // divisor fiddled to make voltage reading correct ! + return field_volt_reading * 40.12; // divisor fiddled to make voltage reading correct ! } double Read_Ammeter () @@ -249,10 +257,27 @@ } -void query_system (struct parameters & a) { +void query_system (parameters & a) { query_toggle = !query_toggle; } +void set_v_out_opamp (double a) { // 0 to 1.0 sets opamp output in range 0 to 5v, charge pump permitting + A_OUT = a; +} +void set_v_out_opamp (parameters & a) { // 0 to 1.0 sets opamp output in range 0 to 5v, charge pump permitting + A_OUT = a.dbl[0] / 100.0; +} + +void charge_pump_override (int a) { // 0 disables, !0 enables charge pump + if (a == 0) + charge_pump_enable = false; + else + charge_pump_enable = true; +} +void charge_pump_override (parameters & a) { // 0 disables, !0 enables charge pump + charge_pump_override ((int)a.dbl[0]); +} + void set_pwm (double d) { // Range 0.0 to 1.0 called from cli Field.set_pwm (d); } @@ -324,7 +349,7 @@ Field.maketable () ; // Here to ensure eeprom has been setup Field.set_for_speed (0); - Engine.Speed_Control (((double)user_settings.rd(WARMUP_SERVO_POS)) / 100.0); + Engine.Set_Speed_Lever (((double)user_settings.rd(WARMUP_SERVO_POS)) / 100.0); startup_delay = user_settings.rd(WARM_UP_DELAY); pc.printf ("Operating Mode is [%s]\r\n", get_mode_text (user_settings.rd(OP_MODE))); @@ -338,22 +363,22 @@ #endif command_line_interpreter () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true // A to D converters all read at 100 Hz - if (flag_link_V_rd) { + if (flag_link_V_rd) { // Reads main alternator output and/or traction battery voltage flag_link_V_rd = false; link_volt_reading *= (1.0 - vfilt); // link_volt_reading += vfilt * (double) Ain_Link_Volts.read(); // Volt fiddle factor NOT corrected here } - if (flag_Pot_rd) { + if (flag_Pot_rd) { // Reads Driver's speed control potentiometer flag_Pot_rd = false; driver_pot *= (1.0 - filt); driver_pot += filt * ((double)Driver_Pot.read() * 1.5); // Includes bodge around zener over-clipping input } - if (flag_A_rd) { + if (flag_A_rd) { // Reads ammeter - user wires this to suit their purpose flag_A_rd = false; amp_reading *= (1.0 - ampfilt); - amp_reading += ampfilt * ((double) Ammeter_In.read() - 0.5); // Amp range NOT corrected here + amp_reading += ampfilt * ((double) Ammeter_In.read() - 0.495); // Amp range NOT corrected here BUT OFFSET IS } - if (flag_field_V_rd) { + if (flag_field_V_rd) { // Reads 'Field Positive' supply - from battery via diode, also alternator rectifier out flag_field_V_rd = false; field_volt_reading *= (1.0 - vfilt); // field_volt_reading += vfilt * (double) Field_Supply_V.read(); // Volt fiddle factor NOT corrected here @@ -401,16 +426,19 @@ "6\tControl Engine by Current Load", */ case SAFE_NOTHING: // Safe nothing mode for cli cmd testing - // Use this to test command line commands e.g. Speed_Control, direct field setting etc + // Use this to test command line commands e.g. Set_Speed_Lever, direct field setting etc break; case POT_SERVO_DIRECT: // Driver_pot --> servo direct. Field OFF - Engine.Speed_Control (driver_pot); - Field.set_for_speed (0); // Safe, no output +// Engine.Set_Speed_Lever (driver_pot); + Engine.Set_Speed_Lever (driver_pot); + REF_VAR = driver_pot; +// Field.set_for_speed (0); // Safe, no output + Field.set_for_speed (3000); // Safe, no output break; case VARIABLE_VOLTAGE: // Variable Voltage - Engine.Speed_Control (driver_pot); // Driver_pot --> servo direct. Field ON + Engine.Set_Speed_Lever (driver_pot); // Driver_pot --> servo direct. Field ON if (driver_pot > DRIVER_NEUTRAL) // if pot not close to zero Field.set_for_speed (Engine.RPM_latest()); // according to RPM else @@ -522,7 +550,7 @@ if (startup_delay == 0) { up_and_running = true; pc.printf ("Warmup ended, starting proper ops\r\n"); - Engine.Speed_Control (0.0); + Engine.Set_Speed_Lever (0.0); } else { pc.printf ("In Startup warmup delay %d\r", startup_delay--);
--- a/rpm.cpp Fri Aug 07 13:06:03 2020 +0000 +++ b/rpm.cpp Sat Dec 05 12:40:17 2020 +0000 @@ -18,7 +18,7 @@ // microsecs.reset () ; // timer = 0 // microsecs.start () ; // 64 bit, counts micro seconds and times out in half million years servo_position = MIN_WORKING_THROTTLE; - Speed_Control (MIN_WORKING_THROTTLE); + Set_Speed_Lever (MIN_WORKING_THROTTLE); }; void Engine_Manager::magneto_timeoutC () @@ -75,7 +75,7 @@ return (uint32_t)filtered_measured_RPM; } -void Engine_Manager::Speed_Control (double th) // Make this private once all throttle refs local +void Engine_Manager::Set_Speed_Lever (double th) // Make this private once all throttle refs local { if (user_settings.rd(SERVO_DIR) == 0) Speed_ControlServo = th; @@ -91,13 +91,13 @@ if (!rpm_in_run_range) { // Transition from idle to working revs rpm_in_run_range = true; servo_position = MIN_WORKING_THROTTLE; // set throttle to probably somewhere near low useful revs - Speed_Control (MIN_WORKING_THROTTLE); + Set_Speed_Lever (MIN_WORKING_THROTTLE); } // Endof transition from idle to working revs } // Endof Runnable or make runnable else { // requested rpm are below useful, so kill engine if (rpm_in_run_range) { // detect transition from useful work to idle servo_position = 0.0; - Speed_Control (0.0); + Set_Speed_Lever (0.0); rpm_in_run_range = false; } } @@ -148,7 +148,7 @@ servo_position = MIN_WORKING_THROTTLE; if (servo_position > MAX_WORKING_THROTTLE) servo_position = MAX_WORKING_THROTTLE; - Speed_Control (servo_position); // Update signal to engine throttle control servo + Set_Speed_Lever (servo_position); // Update signal to engine throttle control servo } break; default:
--- a/rpm.h Fri Aug 07 13:06:03 2020 +0000 +++ b/rpm.h Sat Dec 05 12:40:17 2020 +0000 @@ -35,7 +35,7 @@ // Timer microseconds; public: Engine_Manager (PinName magneto_signal, PinName cleaned_output, PinName for_servo) ; // - void Speed_Control (double); + void Set_Speed_Lever (double); bool running (); void manager_core(); double get_servo_position ();