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
Diff: cli.cpp
- Revision:
- 3:43cb067ecd00
- Parent:
- 2:8e7b51353f32
- Child:
- 5:6ca3e7ffc553
--- a/cli.cpp Mon Jun 08 13:46:52 2020 +0000 +++ b/cli.cpp Mon Jul 27 08:44:59 2020 +0000 @@ -5,38 +5,62 @@ Also usable as comms subsystem in finished code for accepting commands, reporting data etc. */ #include "mbed.h" +#include "field.h" #include "Alternator.h" -//#include "BufferedSerial.h" +#include "BufferedSerial.h" #include <cctype> using namespace std; -extern eeprom_settings user_settings ; -//eeprom_settings mode ; +ee_settings_2020 user_settings ; -//extern int ver, vef, measured_pw_us; -extern void set_throttle_limit (struct parameters & a) ; -//extern void speed_control_factor_set (struct parameters & a) ; +extern BufferedSerial pc; +extern void maketable () ; extern void query_system (struct parameters & a) ; extern uint32_t ReadEngineRPM () ; -extern double Read_BatteryVolts () ; -//extern void Read_Ammeter (double *) ; - - - - - -// WithOUT RTOS -//extern BufferedSerial pc; +extern double Read_Link_Volts () ; +extern double Read_Field_Volts () ; +extern double Read_Ammeter () ; -#ifdef TARGET_NUCLEO_L432KC // -extern Serial pc; -#else -extern BufferedSerial pc; -#endif -//extern double test_pot; // These used in knifeandfork code testing only -extern void maketable () ; +//bool ee_settings_2020::wr (char c, uint32_t i) { // Write one setup char value to private buffer 'settings' +/* +void slope_cmd (struct parameters & a) { + Provides a quick way of filling lookup table. + Sets percent at 3000 RPM with first parameter 0 to 100 +*/ +void slope_cmd (struct parameters & a) { // Requires two params. First %@ 3000 rpm, second slope MAX +/-20 % per krpm above + const int startat = 1800; // rpm to start at + const int rpm_per = 200; // rpm per lookup table step + const int threshold = startat / rpm_per; + signed char at_power_beyond, slope; + pc.printf ("Slope - set pct = %d @ 3krpm, slope %d pct above\r\n", (int32_t)a.dbl[0], (int32_t)a.dbl[1]); + if (a.numof_dbls != 2) + pc.printf ("Need 2 params in slope, got %d, ", a.numof_dbls); + else { + pc.printf ("Got slope params %.1f, %.1f\r\n", a.dbl[0], a.dbl[1]); + if (a.dbl[0] > 100.0) a.dbl[0] = 100.0; + if (a.dbl[0] < 0.0) a.dbl[0] = 0.0; + if (a.dbl[1] > +20.0) a.dbl[1] = +20.0; + if (a.dbl[1] < -20.0) a.dbl[1] = -20.0; + at_power_beyond = (signed char)a.dbl[0]; + slope = (signed char)a.dbl[1]; + pc.printf ("Setting slope "); + for (int i = 0; i < threshold; i++) { // Zero all very low speed settings + user_settings.wr (0, i); + } + for (int i = threshold; i < 21; i++) { + user_settings.wr (at_power_beyond, i); + pc.printf ("%d, ", at_power_beyond); + at_power_beyond += slope; + if (at_power_beyond < 0) at_power_beyond = 0; + if (at_power_beyond > 100) at_power_beyond = 100; + } + pc.printf ("\r\nDone\r\n"); + user_settings.save (); + maketable (); + } +} -void table_tweak_cmd (struct parameters & a) { // Requires two params. First '20', '25' etc representing hundreds RPM. Second 0 to 99 percent +void table_tweak_cmd (struct parameters & a) { // Requires two params. First '20', '22' etc representing hundreds RPM. Second 0 to 99 percent char txt[100]; uint32_t d[3]; txt[0] = 0; @@ -44,9 +68,9 @@ sprintf (txt, "Need 2 params, got %d, ", a.numof_dbls); else { d[2] = (uint32_t)a.dbl[0]; - d[0] = d[2] / 5; + d[0] = d[2] / 2; d[1] = (uint32_t)a.dbl[1]; - if (d[0] > 16 || d[1] > 99 || d[2] != d[0] * 5) + if (d[0] > 20 || d[1] > 100 || d[2] != d[0] * 2) sprintf (txt + strlen(txt), "Param out of range %d, %d, ", d[2], d[1]); else { pc.printf ("Off to reset table %d RPM, %d percent\r\n", d[2] * 100, d[1]); @@ -61,115 +85,169 @@ pc.printf ("Good in table_tweak_cmd, RPM=%d, percentage=%d\r\n", d[0] * 500, d[1]); } -//extern int numof_eeprom_options2 ; -//extern struct optpar const option_list2[] ; -extern struct optpar option_list2[] ; + +//extern VEXT_Data Field; +extern FieldControl Field; + +extern int32_t set_engine_RPM_lit (uint32_t RPMrequest) ; // Returns speed error pos or neg +extern int32_t set_engine_RPM_pct (uint32_t RPMrequest) ; // Returns speed error pos or neg +void ss_cmd (struct parameters & a) { // Set engine Speed 0 - 8000 RPM + uint32_t v = (uint32_t) a.dbl[0]; + pc.printf ("Setting engine RPM to %d, measured RPM returned = %d\r\n", v, set_engine_RPM_lit (v)); +} -/**void mode_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents -* mode_cmd called only from pc comms. No sense calling from Touch Screen Controller -* -* Called without parameters - Lists to pc terminal current settings -* -*/ -void mode19_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents -{ +void sp_cmd (struct parameters & a) { // Set engine Speed 0 - 8000 RPM + uint32_t v = (uint32_t) a.dbl[0]; + pc.printf ("Setting engine RPM percent to %d, measured RPM returned = %d\r\n", v, set_engine_RPM_pct (v)); +} + +void rfcmd (struct parameters & a) { // +// pc.printf ("Field.measured_period = %u", (uint32_t)Field.get_measured_period()); +// pc.printf (", Field.measured_pw_us = %u, duty_cycle = %.3f\r\n", (uint32_t)Field.measured_pw_us, Field.duty_cycle()); + pc.printf ("Field duty cycle measured = %.3f\r\n", Field.get_duty_ratio()); +} + +void vcmd (struct parameters & a) { + pc.printf ("link volts %.2f, field volts %.2f\r\n", Read_Link_Volts(), Read_Field_Volts()); +} + +void acmd (struct parameters & a) { + pc.printf ("amps %.2f\r\n", Read_Ammeter()); +} + - char temps[36]; - int i; - pc.printf ("\r\nmode - Set system data in EEPROM - Jan 2019\r\nSyntax 'mode' with no parameters lists current state.\r\n"); - if (a.numof_dbls) { // If more than 0 parameters supplied - for (i = 0; i < a.numof_dbls; i++) - temps[i] = (char)a.dbl[i]; // recast doubles to char - while (i < 33) - temps[i++] = 0; - i = (int)a.dbl[0]; - switch (i) { - case 0: case 1: case 2: case 3: case 4: - case 5: case 6: case 7: case 8: - if (temps[1] >= option_list2[i].min && temps[1] <= option_list2[i].max) - user_settings.wr(temps[1], RPM0 + i); - break; - case 37: // set pwm scale factor - if (temps[1] >= option_list2[PWM_SCALE].min && temps[1] <= option_list2[PWM_SCALE].max) - user_settings.wr(temps[1], PWM_SCALE); - break; - case 83: // set to defaults - user_settings.set_defaults (); - break; - case 9: // 9 Save settings - user_settings.save (); - pc.printf ("Saving settings to EEPROM\r\n"); - break; - default: - break; - } // endof switch - } // endof // If more than 0 parameters supplied - else { - pc.printf ("No Changes\r\n"); +extern void set_pwm (double) ; // Range 0.0 to 1.0 +void fls_cmd (struct parameters & a) { + pc.printf ("Setting field.limiter to %d percent\r\n", (int)a.dbl[0]); + set_pwm (a.dbl[0] / 100.0); +} + +void set_defaults_cmd (struct parameters & a) { + struct sldandt * p = NULL; + bool flag = true; + int i = 0; + while (flag) { + p = user_settings.inform(i); // Returns NULL when i goes out of range + if (p == NULL) + flag = false; + else { + pc.printf ("min %d, max %d, default %d, text %s\r\n", p->min, p->max, p->de_fault, p->txt); + user_settings.wr (p->de_fault, i); + i++; + } } - pc.printf ("mode 0\t%s, [%d]\r\n", option_list2[0].t, user_settings.rd(RPM0)); - pc.printf ("mode 1\t%s, [%d]\r\n", option_list2[1].t, user_settings.rd(RPM1)); - pc.printf ("mode 2\t%s, [%d]\r\n", option_list2[2].t, user_settings.rd(RPM2)); - pc.printf ("mode 3\t%s, [%d]\r\n", option_list2[3].t, user_settings.rd(RPM3)); - pc.printf ("mode 4\t%s, [%d]\r\n", option_list2[4].t, user_settings.rd(RPM4)); - pc.printf ("mode 5\t%s, [%d]\r\n", option_list2[5].t, user_settings.rd(RPM5)); - pc.printf ("mode 6\t%s, [%d]\r\n", option_list2[6].t, user_settings.rd(RPM6)); - pc.printf ("mode 7\t%s, [%d]\r\n", option_list2[7].t, user_settings.rd(RPM7)); - pc.printf ("mode 8\t%s, [%d]\r\n", option_list2[8].t, user_settings.rd(RPM8)); + user_settings.save (); +} - pc.printf ("mode 37\t%s, [%d]\r\n", option_list2[PWM_SCALE].t, user_settings.rd(PWM_SCALE)); - pc.printf ("mode 83\tSet to defaults\r\n"); - pc.printf ("mode 9\tSave settings\r\r\n"); - +void servodir_cmd (struct parameters & a) { + char ch = (char)a.dbl[0]; + if (a.numof_dbls != 1 || ch > 1) { + pc.printf ("Wrong servodir set\r\n"); + return ; + } + if (user_settings.rd(SERVO_DIR) != ch) { + pc.printf ("Setting servo dir %.1f \r\n", a.dbl[0]); + user_settings.wr(ch, SERVO_DIR); + user_settings.save(); + } } -/*void gpcmd (struct parameters & a) { - pc.printf ("pwm=%.3f\r\n", user_settings.get_pwm ((int)a.dbl[0])); -}*/ +char * modes_txt[] = { + "0\tSafe nothing mode for cli cmd testing", + "1\tPot to Servo direct, field OFF", + "2\tVariable voltage", + "3\tFixed voltage", + "4\tEngine Revs Control", + "5\tSet Engine to Driver's Pot", + "6\tControl Engine by Current Load", + "7\tAuto Test", +} ; + +int numof_op_modes = sizeof(modes_txt) / sizeof(char *); -extern VEXT_Data Field; +char * get_mode_text (uint32_t mode) { + if (mode > numof_op_modes) { + pc.printf ("mode OOR in get_mode_text, %d\r\n", mode); + mode = numof_op_modes - 1; + } + return modes_txt[mode]; +} -void rfcmd (struct parameters & a) { // Note casts all wrong here, values are 64 bit - pc.printf ("Field.measured_period = %u", (uint32_t)Field.measured_period); - pc.printf (", Field.measured_pw_us = %u, duty_cycle = %.3f\r\n", (uint32_t)Field.measured_pw_us, Field.duty_cycle()); +void mode20_cmd (struct parameters & a) ; +void mode_cmd (struct parameters & a) { + if (a.numof_dbls == 1 && (uint32_t) a.dbl[0] <= numof_op_modes) { + a.dbl[1] = a.dbl[0]; + a.dbl[0] = OP_MODE; //23.0; + a.numof_dbls = 2; + mode20_cmd (a); + return; + } + pc.printf ("Current mode is %d \r\nTo set operating mode, use mode n :- where \r\n", user_settings.rd(OP_MODE)); + for (int i = 0; i < numof_op_modes; i++) + pc.printf ("%s\r\n", get_mode_text(i)); } -//extern void set_RPM_demand (uint32_t d) ; - -/*void set_rpm_cmd (struct parameters & a) { - pc.printf ("setting RPM to %d\r\n",(int)a.dbl[0]); - set_RPM_demand ((uint32_t)a.dbl[0]); -}*/ - -/*void speedcmd (struct parameters & a) { - int s = ReadEngineRPM (); - pc.printf ("speed %d, pwm %.3f\r\n", s, user_settings.get_pwm(s)); -}*/ - -void vcmd (struct parameters & a) { - pc.printf ("volts %.2f\r\n", Read_BatteryVolts()); +void mode20_cmd (struct parameters & a) { + struct sldandt * p = NULL; // Pointer to struct containing max, min and default values, and brief text descriptor for a command + int i = 0; + bool flag = true; + bool save_settings = false; + int32_t cmd_num = (int32_t) a.dbl[0], first_p = (int32_t) a.dbl[1]; + pc.printf ("At user setting, numofparams = %d, dbl[0]=%.2f, dbl[1]=%.2f\r\n", a.numof_dbls, a.dbl[0], a.dbl[1]); + if (a.numof_dbls < 2) { // Need at least command number followed by at least one parameter + pc.printf ("Listing Setup\r\nTo alter, enter us param number, new value\r\n"); + while (flag) { + p = user_settings.inform(i); // Returns false when i goes out of range + if (p == NULL) + flag = false; + else { + pc.printf ("%d\tval %d, min %d, max %d, default %d, text %s\r\n", i, user_settings.rd(i), p->min, p->max, p->de_fault, p->txt); + i++; + } + } + return ; + } // When too few parameters, output list. Done. + p = user_settings.inform(cmd_num); // Set pointer to min, max, default and text info + if (p == NULL) { + pc.printf ("Invalid command number %d in user setting entry\r\n", cmd_num); + return ; + } + if (first_p < p->min || first_p > p->max) { + pc.printf ("%s\r\nParameter min %d, max %d, you entered %d. Not setting\r\n", p->txt, p->min, p->max, first_p); + return ; + } + pc.printf ("Hoping to set [%s] to %d\r\n", p->txt, first_p); + switch (cmd_num) { + case OP_MODE: // + case WARM_UP_DELAY: + case WARMUP_SERVO_POS: + case SPEED_CTRL_P: + case SERVO_DIR: + i = user_settings.rd(cmd_num); + if (i == first_p) + pc.printf ("No need, [%s] already set to %d\r\n", p->txt, i); + else { + user_settings.wr((char)first_p, cmd_num); + save_settings = true; + pc.printf ("Setting [%s] to %d\r\n", p->txt, first_p); + } + break; + default: + pc.printf ("No code for [%s]\r\n", p->txt); + break; + } + if (save_settings) + user_settings.save(); } -/*void icmd (struct parameters & a) { - double results[4]; - //double * ampsptr = - Read_Ammeter(results) ; - pc.printf ("amps %.3f, offset %.3f\r\n", results[0], results[1]); -}*/ - -extern void set_servo (double p) ; // Only for test, called from cli - -void set_servo_cmd (struct parameters & a) { - double p = a.dbl[0] / 100.0; - pc.printf ("servo %.2f\r\n", p); - set_servo (p); +extern void auto_test_initiate (int bulb_count) ; +void auto_test_kickoff_cmd (struct parameters & a) { + auto_test_initiate ((int)a.dbl[0]); } -extern bool set_pwm (double) ; // Range 0.0 to 1.0 -void p_cmd (struct parameters & a) { -// int32_t i = (int32_t)a.dbl[0]; - pc.printf ("Setting PWM to %d percent\r\n", (int)(a.dbl[0] * 100.0)); - set_pwm (a.dbl[0]); +void test_Fsfs_cmd (struct parameters & a) { + uint32_t rpm = (uint32_t)a.dbl[0]; + pc.printf ("Field.set_for_speed %d returned %d\r\n", rpm, Field.set_for_speed(rpm)); } void null_cmd (struct parameters & a) { @@ -186,22 +264,23 @@ struct kb_command const command_list[] = { {"?", "Lists available commands, same as ls", menucmd}, - {"tt", "Table Tweak - 2 params RPM/100, percentage 0-99", table_tweak_cmd}, + {"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}, + {"sd", "Set User Settings Defaults", set_defaults_cmd}, + {"us", "Set User Settings", mode20_cmd}, + {"tt", "Table Tweak 0 - 100", table_tweak_cmd}, + {"ss", "Set Speed 0 - 8000 RPM", ss_cmd}, + {"sp", "Set Speed 0 - 100 percent", sp_cmd}, +// {"tl", "Throttle logger tester, enter param 0.0 - 1.0", throt_log_cmd}, {"rf", "Check rise and fall on VEXT", rfcmd}, -// {"s", "Speed, RPM", speedcmd}, {"v", "Read Battery volts", vcmd}, -// {"i", "Read Ammeter", icmd}, - {"p", "Set PWM 0 to 2400???", p_cmd}, + {"i", "Read Ammeter", acmd}, + {"fl", "Field limiter set 0 to 99 percent", fls_cmd}, + {"mode", "Set operating mode - as us23", mode_cmd}, + {"slope", "Field limiter set pct 0 to 99 @3k, slope pct per k above", slope_cmd}, {"q", "Query system - toggle message stream on/off", query_system}, -// {"gp","Get pwm from RPM", gpcmd}, - {"mode", "See or set eeprom values", mode19_cmd}, {"nu", "do nothing", null_cmd}, -#ifndef SPEED_CONTROL_ENABLE // Includes engine revs servo control loop - {"ser","set throttle servo direct 0 - 99", set_servo_cmd}, -#endif -// {"sf","set speed control factor", speed_control_factor_set}, -// {"sv","set engine RPM demand 2500 - 6000", set_rpm_cmd}, - {"tl","set throttle_limit 0.0-1.0", set_throttle_limit}, }; const int numof_menu_items = sizeof(command_list) / sizeof(kb_command); @@ -249,7 +328,7 @@ param_block.dbl[k] = 0.0; } param_block.position_in_list = i; - param_block.last_time = clock (); + //param_block.last_time = clock (); param_block.numof_dbls = 0; pEnd = cmd_line + wrdlen; while (*pEnd) { // Assemble all numerics as doubles @@ -261,7 +340,7 @@ pc.printf ("\r\n"); // for (int k = 0; k < param_block.numof_dbls; k++) // pc.printf ("Read %.3f\r\n", param_block.dbl[k]); - param_block.times[i] = clock(); +// param_block.times[i] = clock(); command_list[i].f(param_block); // execute command i = numof_menu_items + 1; // to exit for loop } // end of match found