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:
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