STM3 ESC dual brushless motor controller. 10-60v, motor power rating tiny to kW. Ganged or independent motor control As used in 'The Brute' locomotive - www.jons-workshop.com

Dependencies:   mbed BufferedSerial Servo FastPWM

Revision:
12:d1d21a2941ef
Parent:
11:bfb73f083009
--- a/cli_BLS_nortos.cpp	Sat Jan 19 11:45:01 2019 +0000
+++ b/cli_BLS_nortos.cpp	Mon Mar 04 17:51:08 2019 +0000
@@ -1,300 +1,447 @@
-//  DualBLS2018_06
+/**
+*   Code in this file : -
+*
+*   STM3_ESC board uses two serial ports. 
+*       One (use pc.printf etc) provides 9600 baud comms to a pc or other terminal. Essential for test and setup, not used in everyday use.
+*
+*       com2 provides 19200 baud comms via opto-isolators to Touch Screen Controller (see "Brute_TS_Controller_2018_11"). Opto isolation allows
+*       for several boards to parallel up on this port, each STM3_ESC board having a unique single byte ID char in range '0' to '9'.
+*       This enables Touch Screen controller to address ESC boards individually e.g. for requesting speed, RPM etc
+*       while also allowing broadcast of commands not requiring responses
+*
+*   Code implements a Command Line Interpreter (see class   cli_2019)
+*   Two instantiations of class   cli_2019 are used, 'pcc' for pc comms and 'tsc' for touch screen comms
+*   These read incoming commands and execute code functions accordingly. These functions are all of type
+*       void    func    (struct parameters &)  ;
+*   This allows any command line parameters to pass to 'func'
+*/
+//  Brushless_STM3_Ctrl_2018_11
 #include "mbed.h"
 #include "BufferedSerial.h"
-#include "FastPWM.h"
 #include "DualBLS.h"
 #include "brushless_motor.h"
 
 #include <cctype>
-#include "DualBLS.h"
 using namespace std;
 
-extern  int I_Am    ()  ;      //  Returns boards id number as ASCII char '0', '1' etc. Code for Broadcast = '\r'
+extern  eeprom_settings     mode     ;
+extern  error_handling_Jan_2019     ESC_Error    ;         //  Provides array usable to store error codes.
 extern  int     WatchDog;
 extern  bool    WatchDogEnable;
-extern  char    mode_bytes[];
-
-extern  brushless_motor MotorA, MotorB;
+extern  double  rpm2mph ;
 
-const int   BROADCAST   = '\r';
-const   int MAX_PARAMS = 20;
-struct  parameters  {
-    struct kb_command const * command_list;
-    BufferedSerial * com;   //  pc or com2
-    char    cmd_line[120];
-    char    * cmd_line_ptr;
-    int32_t position_in_list, numof_dbls, target_unit, numof_menu_items, cl_index, gp_i;
-    double  dbl[MAX_PARAMS];
-    bool    respond, resp_always;
-}   ;
+extern  brushless_motor MotorA, MotorB;     //  Controlling two motors together or individually
+extern  char   const_version_string[]   ;
 
-struct parameters pccom, lococom;
-//  WithOUT RTOS
-extern  BufferedSerial com2, pc;
-extern  void    send_test   ()  ;
-extern  void    setVI   (double v, double i)  ;
-extern  void    setV    (double v)  ;
-extern  void    setI    (double i)  ;
-//extern  void    last_VI    (double * val)  ;   //  only for test from cli
-
-//BufferedSerial * com;
+extern  BufferedSerial com2, pc;            //  The two com ports used. There is also an unused com port, com3 setup @ 1200 baud
+extern  void    setVI   (double v, double i)  ;     //  Set motor voltage limit and current limit
 extern  double  Read_DriverPot  ();
 extern  double  Read_BatteryVolts   ();
-void    pot_cmd (struct parameters & a)
+extern  void    mode_set_both_motors   (int mode, double val)  ;   //  called from cli to set fw, re, rb, hb
+extern  void    rcin_report ()  ;
+
+//  All void    func    (struct parameters &)  ; functions addressed by command line interpreter are together below here
+
+/**
+void    ver_cmd (struct parameters & a)
+    Responds YES, causes action NO
+    PC or TS able to read software / firmware / hardware version string
+*/
+void    ver_cmd (struct parameters & a)
 {
-    pc.printf   ("Driver's pot %.3f\r\n", Read_DriverPot  ());
+    if  (a.source == SOURCE_PC)
+        pc.printf   ("Version %s\r\n", const_version_string);
+    else    {
+        if  (a.source == SOURCE_TS)
+            if (a.respond)     //  Only respond if this board addressed
+                a.com->printf   ("%s\r", const_version_string);
+        else
+            pc.printf   ("Crap source %d in ver_cmd\r\n", a.source);
+    }
 }
 
+/**
+void    pot_cmd (struct parameters & a)
+    Responds YES, causes action NO
+    pc reads DriverPot. No sense in TS reading as STM3_ESC uses either/or TS, DriverPot
+*/
+void    pot_cmd (struct parameters & a)
+{   if  (a.source == SOURCE_PC)
+        pc.printf   ("Driver's pot %.3f\r\n", Read_DriverPot  ());
+    else
+        pc.printf   ("Wrong use of pot_cmd\r\n");
+}
+
+/**
+*   Do nothing command, but does report board ID code '0' to '9'
+*/
 void    null_cmd (struct parameters & a)
 {
     if  (a.respond) 
-        a.com->printf   ("At null_cmd, board ID %c, parameters : First %.3f, second %.3f\r\n", I_Am(), a.dbl[0], a.dbl[1]);
-}
-
-//    {"wden", "enable watchdog if modes allow", wden_lococmd},
-//    {"wddi", "disable watchdog always", wddi_lococmd},
-
-void    wden_lococmd (struct parameters & a)
-{
-    if  (mode_bytes[COMM_SRC] != 3)     //  When not hand pot control, allow watchdog enable
-        WatchDogEnable  = true;
-}
-void    wden_pccmd (struct parameters & a)
-{
-    wden_lococmd    (a);
-    a.com->printf   ("Watchdog %sabled\r\n", WatchDogEnable ? "En":"Dis");
+        a.com->printf   ("At null_cmd, board ID %c\r\n", mode.rd(BOARD_ID));
 }
 
-void    wddi_lococmd (struct parameters & a)
-{
-    WatchDogEnable  = false;
-}
-void    wddi_pccmd (struct parameters & a)
-{
-    wddi_lococmd    (a);
-    a.com->printf   ("Watchdog %sabled\r\n", WatchDogEnable ? "En":"Dis");
-}
-
-extern  void    report_motor_types  ()  ;
+#ifdef  USING_DC_MOTORS
+/**
+void    mt_cmd (struct parameters & a)
+    PC Only
+    Responds YES, causes action NO
+    report_motor_types  ()      //  Reports 'Brushless' if Hall inputs read 1 to 6, 'DC' if no Hall sensors connected, therefore DC motor assumed
+*/
 void    mt_cmd (struct parameters & a)
 {
-    report_motor_types  ();
-//    if  (a.respond) 
-//        a.com->printf   ("At null_cmd, board ID %c, parameters : First %.3f, second %.3f\r\n", I_Am(), a.dbl[0], a.dbl[1]);
+    if  (a.source == SOURCE_PC)
+        pc.printf   ("Mot A is %s, Mot B is %s\r\n", MotorA.dc_motor ? "DC":"Brushless", MotorB.dc_motor ? "DC":"Brushless");
+    else
+        pc.printf   ("Wrong use of mt_cmd\r\n");
+}
+#endif
+
+/**
+*   void    rdi_cmd (struct parameters & a)  //  read motor currents (uint32_t) and BatteryVolts (double)
+*/
+void    rdi_cmd (struct parameters & a)  //  read motor currents (uint32_t) and BatteryVolts (double)
+{   //  Voltage reading true volts, currents only useful as relative values
+    if  (a.respond) 
+//        a.com->printf ("rdi%d %d %.1f\r%s", MotorA.I.ave, MotorB.I.ave, Read_BatteryVolts  (), a.source == SOURCE_PC ? "\n" : "");
+        a.com->printf ("rdi%.1f %.1f %.1f\r%s", MotorA.Idbl, MotorB.Idbl, Read_BatteryVolts  (), a.source == SOURCE_PC ? "\n" : "");
+          //  Format good to be unpicked by cli in touch screen controller
 }
 
-extern  void    mode_set_both_motors   (int mode, double val)  ;   //  called from cli to set fw, re, rb, hb
-
-void    rdi_cmd (struct parameters & a)  //  read motor currents
-{
-    if  (a.respond) 
-        a.com->printf ("rdi%.0f %.0f %.1f\r", MotorA.I.ave, MotorB.I.ave, Read_BatteryVolts  ());  //  Format good to be unpicked by cli in touch screen controller
-}
-
+/**
+*   void    rvi_cmd (struct parameters & a)  //  read last normalised motor voltage and current values sent to pwms
+*
+*/
 void    rvi_cmd (struct parameters & a)  //  read last normalised values sent to pwms
 {
     if  (a.respond) 
-        a.com->printf ("rvi%.2f %.2f %.2f %.2f\r", MotorA.last_V, MotorA.last_I, MotorB.last_V, MotorB.last_I);
-}
-
-void    fw_cmd (struct parameters & a)  //  Forward command
-{
-    mode_set_both_motors   (FORWARD, 0.0);
+        a.com->printf ("rvi%.2f %.2f %.2f %.2f\r%s", MotorA.last_V, MotorA.last_I, MotorB.last_V, MotorB.last_I, a.source == SOURCE_PC ? "\n" : "");
 }
 
-void    re_cmd (struct parameters & a)  //  Reverse command
+/**
+*   void    fw_cmd (struct parameters & a)  //  Forward command
+*   Broadcast to all STM3_ESC boards, required to ACT but NOT respond
+*/
+void    fw_cmd (struct parameters & a)  //  Forward command
 {
-    mode_set_both_motors   (REVERSE, 0.0);
-}
-
-void    rb_cmd (struct parameters & a)      //  Regen brake command
-{
-    double b = a.dbl[0] / 100.0;
-//    a.com->printf   ("Applying brake %.3f\r\n", b);
-    mode_set_both_motors   (REGENBRAKE, b);
-//    apply_brake (b);
+    mode_set_both_motors   (MOTOR_FORWARD, 0.0);
+    if  (a.source == SOURCE_PC)
+        pc.printf   ("fw\r\n");     //  Show response to action if command from pc terminal
 }
 
-extern  bool    wr_24LC64  (int mem_start_addr, char * source, int length)   ;
-extern  bool    rd_24LC64  (int mem_start_addr, char * dest, int length)   ;
-
-void    erase_cmd (struct parameters & a)       //  Sets eeprom contents to all 0xff. 256 pages of 32 bytes to do
+/**
+*   void    re_cmd (struct parameters & a)  //  Reverse command
+*   Broadcast to all STM3_ESC boards, required to ACT but NOT respond
+*/
+void    re_cmd (struct parameters & a)  //  Reverse command
 {
-    char    t[36];
-    for (int i = 0; i < 32; i++)
-        t[i] = 0xff;
-    for (int i = 0; i < 8191; i += 32)  {
-        a.com->printf (".");
-        if  (!wr_24LC64   (i, t, 32))
-            a.com->printf ("eeprom write prob\r\n");
-    }
-}
-/*struct  motorpairoptions    {   //  This to be user settable in eeprom, 32 bytes
-    uint8_t MotA_dir,   //  0 or 1
-            MotB_dir,   //  0 or 1
-            gang,       //  0 for separate control (robot mode), 1 for ganged loco bogie mode
-            serv1,      //  0, 1, 2 = Not used, Input, Output
-            serv2,      //  0, 1, 2 = Not used, Input, Output
-            cmd_source, //  0 Invalid, 1 COM1, 2 COM2, 3 Pot, 4 Servo1, 5 Servo2
-    {'1', '9', '0', "Alternative ID ascii '1' to '9'"}, //  defaults to '0' before eerom setup for first time
-    {50, 250, 98,  "Wheel diameter mm"},   //  New 01/06/2018
-    {10, 250, 27,  "Motor pinion"},   //  New 01/06/2018
-    {50, 250, 85,  "Wheel gear"},   //  New 01/06/2018
-//            last;
-}   ;
-*/
-
-//  New 22 June 2018
-//  get bogie bytes - report back to touch controller
-void    gbb_cmd (struct parameters & a)       //  
-{
-    if  (a.target_unit == BROADCAST || !a.resp_always) {
-//        a.com->printf ("At mode_cmd, can not use BROADCAST with mode_cmd\r\n");
-    } else    {
-        pc.printf   ("At gbb\r\n");
-        char    eeprom_contents[36];    //  might need to be unsigned?
-        memset  (eeprom_contents, 0, 36);
-        a.com->printf   ("gbb");
-        rd_24LC64   (0, eeprom_contents, 32);
-        for (int i = 0; i < numof_eeprom_options; i++)
-            a.com->printf (" %d", eeprom_contents[i]);
-        a.com->putc ('\r');
-        a.com->putc ('\n');
-    }
+    mode_set_both_motors   (MOTOR_REVERSE, 0.0);
+    if  (a.source == SOURCE_PC)
+        pc.printf   ("re\r\n");
 }
 
-void    mode_cmd (struct parameters & a)       //  With no params, reads eeprom contents. With params sets eeprom contents
+/**
+*   void    rb_cmd (struct parameters & a)      //  Regen brake command
+*   Broadcast to all STM3_ESC boards, required to ACT but NOT respond
+*/
+void    rb_cmd (struct parameters & a)      //  Regen brake command
 {
-    if  (a.target_unit == BROADCAST || !a.resp_always) {
-//        a.com->printf ("At mode_cmd, can not use BROADCAST with mode_cmd\r\n");
-    } else    {
-        char    t[36];
-        a.com->printf ("At mode_cmd with node %d\r\n", a.target_unit);
-        rd_24LC64   (0, t, 32);
-        a.com->printf ("Numof params=%d\r\n", a.numof_dbls);
-        for (int i = 0; i < numof_eeprom_options; i++)
-            a.com->printf ("%2x\t%s\r\n", t[i], option_list[i].t);
-        if  (a.numof_dbls == 0) {   //  Read present contents, do not write
-            a.com->printf ("That's it\r\n");
-        } else    { //  Write new shit to eeprom
-            a.com->printf ("\r\n");
-            if  (a.numof_dbls != numof_eeprom_options) {
-                a.com->printf ("params required = %d, you offered %d\r\n", numof_eeprom_options, a.numof_dbls);
-            } else    { //  Have been passed correct number of parameters
-                int b;
-                a.com->printf("Ready to write params to eeprom\r\n");
-                for (int i = 0; i < numof_eeprom_options; i++) {
-                    b = (int)a.dbl[i];  //  parameter value to check against limits
-                    if  (i == 6)    //  Alternative ID must be turned to ascii
-                        b |= '0';
-                    if  ((b < option_list[i].min) || (b > option_list[i].max))  {   //  if parameter out of range
-                        a.com->printf("Warning - Parameter = %d, out of range, setting to default %d\r\n", b, option_list[i].def);
-                        b = option_list[i].def;
-                    }
-                    a.com->printf ("0x%2x\t%s\r\n", (t[i] = b), option_list[i].t);
-                }
-                wr_24LC64   (0, t, numof_eeprom_options);
-                memcpy  (mode_bytes,t,32);
-                a.com->printf("Parameters set in eeprom\r\n");
-            }
-        }
-    }
+    mode_set_both_motors   (MOTOR_REGENBRAKE, a.dbl[0] / 100.0);
+    if  (a.source == SOURCE_PC)
+        pc.printf   ("rb %.2f\r\n", a.dbl[0] / 100.0);
 }
-/*void    coast_cmd (struct parameters & a)   {   //  Coast
 
-}
+/**
+*   void    hb_cmd (struct parameters & a)      //  Hand brake command
+*   Broadcast to all STM3_ESC boards, required to ACT but NOT respond
+*
+*   NOTE    Jan 2019 Hand brake not implemented
+*
 */
-void    hb_cmd (struct parameters & a)
+void    hb_cmd (struct parameters & a)      //  Hand brake command
 {
     if  (a.respond) {
         a.com->printf   ("numof params = %d\r\n", a.numof_dbls);
         a.com->printf   ("Hand Brake : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
     }
-    mode_set_both_motors   (HANDBRAKE, 0.0);
+    mode_set_both_motors   (MOTOR_HANDBRAKE, 0.0);
 }
 
-extern  uint32_t    last_temp_count;
+
+extern  int numof_eeprom_options2    ;
+extern  struct  optpar const option_list2[]  ;
+/**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
+{
+    char            temps[36];
+    int i;
+    double  topspeed;   //  New Jan 2019 - set max loco speed
+    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;
+        switch  ((int)a.dbl[0]) {
+            case    0:      //  MotorA_dir [0 or 1], MotorB_dir [0 or 1]
+                if  (temps[1] == 0 || temps[1] == 1)
+                    mode.wr(temps[1], MOTADIR);
+                if  (temps[2] == 0 || temps[2] == 1)
+                    mode.wr(temps[2], MOTBDIR);
+                break;
+            case    1:      //  MotorA_poles [4,6,8], MotorB_poles [4,6,8]
+                if  (temps[1] == 4 || temps[1] == 6 || temps[1] == 8)
+                    mode.wr(temps[1], MOTAPOLES);
+                if  (temps[2] == 4 || temps[2] == 6 || temps[2] == 8)
+                    mode.wr(temps[2], MOTBPOLES);
+                break;
+            case    2:      //  MotorA_ current sense resistors [1 to 4], MotorB_ current sense resistors [1 to 4]
+                if  (temps[1] > 0 && temps[1] < 5) 
+                    mode.wr(temps[1], MOTADIR);
+                if  (temps[2] > 0 && temps[2] < 5)  
+                    mode.wr(temps[2], MOTBDIR);
+                break;
+            case    3:      //  2 Servo1 [0 or 1], Servo2 [0 or 1]
+                if  (temps[1] == 0 || temps[1] == 1)
+                    mode.wr(temps[1], SVO1);
+                if  (temps[2] == 0 || temps[2] == 1)
+                    mode.wr(temps[2], SVO2);
+                break;
+            case    4:      //  3 RCIn1 [0 or 1], RCIn2 [0 or 1]
+                if  (temps[1] == 0 || temps[1] == 1)
+                    mode.wr(temps[1], RCIN1);
+                if  (temps[2] == 0 || temps[2] == 1)
+                    mode.wr(temps[2], RCIN2);
+                break;
+            case    5:      //  4 Board ID '0' to '9'
+                if  (temps[1] <= 9)    //  pointless to compare unsigned integer with zero
+                    mode.wr('0' | temps[1], BOARD_ID);
+                break;
+            case    6:      //  TOP_SPEED
+                topspeed = a.dbl[1];
+                if  (topspeed > 25.0)   topspeed = 25.0;
+                if  (topspeed < 1.0)    topspeed = 1.0;
+                mode.wr((char)(topspeed * 10.0), TOP_SPEED);
+                break;
+            case    7:      //  5 Wheel dia mm, Motor pinion teeth, Wheel gear teeth
+                mode.wr(temps[1], WHEELDIA);
+                mode.wr(temps[2], MOTPIN);
+                mode.wr(temps[3], WHEELGEAR);
+                break;
+            case    8:      //    {2, 5, 2, "Command source 2= COM2 (Touch Screen), 3= Pot, 4= RC Input1, 5= RC Input2"},
+                if  (temps[1] > 1 && temps[1] < 6)
+                    mode.wr(temps[1], COMM_SRC);
+                break;
+            case    83: //  set to defaults
+                mode.set_defaults   ();
+                break;
+            case    9:      //  9 Save settings
+                mode.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");
+    }
+    pc.printf   ("mode 0\tMotorA_dir [0 or 1]=%d, MotorB_dir [0 or 1]=%d\r\n", mode.rd(MOTADIR), mode.rd(MOTBDIR));
+    pc.printf   ("mode 1\tMotorA_poles [4,6,8]=%d, MotorB_poles [4,6,8]=%d\r\n", mode.rd(MOTAPOLES), mode.rd(MOTBPOLES));
+    pc.printf   ("mode 2\tMotorA I 0R05 sense Rs [1to4]=%d, MotorB I 0R05 sense Rs [1to4]=%d\r\n", mode.rd(ISHUNTA), mode.rd(ISHUNTB));
+    pc.printf   ("mode 3\tServo1 [0 or 1]=%d, Servo2 [0 or 1]=%d\r\n", mode.rd(SVO1), mode.rd(SVO2));
+    pc.printf   ("mode 4\tRCIn1 [0 or 1]=%d, RCIn2 [0 or 1]=%d\r\n", mode.rd(RCIN1), mode.rd(RCIN2));
+    pc.printf   ("mode 5\tBoard ID ['0' to '9']='%c'\r\n", mode.rd(BOARD_ID));
+    pc.printf   ("mode 6\tTop Speed MPH [1.0 to 25.0]=%.1f\r\n", double(mode.rd(TOP_SPEED)) / 10.0);
+    pc.printf   ("mode 7\tWheel dia mm=%d, Motor pinion teeth=%d, Wheel gear teeth=%d\r\n", mode.rd(WHEELDIA), mode.rd(MOTPIN), mode.rd(WHEELGEAR));
+    pc.printf   ("mode 8\tCommand Src [%d] - 2=COM2 (Touch Screen), 3=Pot, 4=RC In1, 5=RC In2\r\n", mode.rd(COMM_SRC));
+    pc.printf   ("mode 83\tSet to defaults\r\n");
+    pc.printf   ("mode 9\tSave settings\r\r\n");
+
+}
+
+extern  uint32_t    last_temperature_count;
+/**
+*   void    temperature_cmd  (struct parameters & a)  {
+*   Few boards have temperature sensor fitted. Non-preferred feature
+*/
 void    temperature_cmd  (struct parameters & a)  {
     if  (a.respond) {
-        a.com->printf ("tem%c %d\r\n", mode_bytes[ID], (last_temp_count / 16) - 50);
+        a.com->printf ("tem%c %d\r\n", mode.rd(BOARD_ID), (last_temperature_count / 16) - 50);
     }
 }
 
-void    bogie_constants_report_cmd  (struct parameters & a)  {
-    if  (a.respond) {
-        a.com->printf ("bc%c %d %d %d\r\n", mode_bytes[ID], mode_bytes[WHEELDIA], mode_bytes[MOTPIN], mode_bytes[WHEELGEAR]);
-    }
-}
-
+/**
+*void    rpm_cmd (struct parameters & a) //  to report e.g. RPM 1000 1000 ; speed for both motors
+*/
 void    rpm_cmd (struct parameters & a) //  to report e.g. RPM 1000 1000 ; speed for both motors
 {
     if  (a.respond) 
-        a.com->printf  ("rpm%d %d\r", MotorA.RPM, MotorB.RPM);
+//        a.com->printf  ("rpm%c %d %d\r%s", mode.rd(BOARD_ID), MotorA.RPM, MotorB.RPM, a.source == SOURCE_PC ? "\n" : "");
+        a.com->printf  ("rpm%c %.0f %.0f\r%s", mode.rd(BOARD_ID), MotorA.dRPM, MotorB.dRPM, a.source == SOURCE_PC ? "\n" : "");
 }
 
-extern  double  rpm2mph ;
-void    mph_cmd (struct parameters & a) //  to report miles per hour
+/**
+*void    mph_cmd (struct parameters & a) //  to report miles per hour
+*/
+void    mph_cmd (struct parameters & a) //  to report miles per hour to 1 decimal place
 {
     if  (a.respond) 
-        a.com->printf ("mph%c %.3f\r", mode_bytes[ID], (double)(MotorA.RPM + MotorB.RPM) * rpm2mph / 2.0);
+//        a.com->printf ("mph%c %.1f\r%s", mode.rd(BOARD_ID), (double)(MotorA.RPM + MotorB.RPM) * rpm2mph / 2.0, a.source == SOURCE_PC ? "\n" : "");
+        a.com->printf ("mph%c %.1f\r%s", mode.rd(BOARD_ID), (double)(MotorA.dMPH + MotorB.dMPH) / 2.0, a.source == SOURCE_PC ? "\n" : "");
+}
+
+/**
+*void    sysV_report (struct parameters & a) //  to report system voltage
+*   Reports system link voltage to one decimal place
+*/
+void    sysV_report (struct parameters & a) //  
+{
+    if  (a.respond) 
+        a.com->printf ("?v%c %.1f\r%s", mode.rd(BOARD_ID), Read_BatteryVolts(), a.source == SOURCE_PC ? "\n" : "");
 }
 
-void    menucmd (struct parameters & a);
+/**
+*void    sysI_report (struct parameters & a) //  to report motor currents
+*   Reports doubles for each motor current amps to 2 decimal places
+*/
+void    sysI_report (struct parameters & a) //  
+{
+    if  (a.respond) //  Calibration, refinement of 6000.0 (not miles out) first guess possible.
+//        a.com->printf ("?i%c %.2f %.2f\r%s", mode_bytes[BOARD_ID], (double)MotorA.I.ave / 6000.0, (double)MotorB.I.ave / 6000.0, a.source == SOURCE_PC ? "\n" : "");
+//        a.com->printf ("?i%c %.2f %.2f\r%s", mode.rd(BOARD_ID), (double)MotorA.I.ave / 6000.0, MotorA.I.dblave2 / 6000.0, a.source == SOURCE_PC ? "\n" : "");
+        a.com->printf ("?i%c %.2f %.2f\r%s", mode.rd(BOARD_ID), MotorA.Idbl, MotorB.Idbl, a.source == SOURCE_PC ? "\n" : "");
+}
 
+
+/**void    vi_cmd (struct parameters & a)
+*
+*   For setting motor voltage and current limits from pc terminal for test   
+*/
 void    vi_cmd (struct parameters & a)
 {
-//    if  (a.respond)
-//        com->printf   ("In setVI, setting V to %.2f, I %.2f\r\n", a.dbl[0], a.dbl[1]);
     setVI   (a.dbl[0] / 100.0, a.dbl[1] / 100.0);
+    pc.printf   ("setVI from %s\r\n", a.source == SOURCE_PC ? "PC" : "Touch Screen");
 }
 
+/**
+*void    v_cmd (struct parameters & a)
+*    Set motor voltage limit from either source without checking for addressed board
+*/
 void    v_cmd (struct parameters & a)
 {
-//    if  (a.respond)
-//        com->printf   ("In setV, setting V to %.2f\r\n", a.dbl[0]);
-    setV   (a.dbl[0] / 100.0);
+    MotorA.set_V_limit  (a.dbl[0] / 100.0);
+    MotorB.set_V_limit  (a.dbl[0] / 100.0);
 }
 
+/**
+*void    i_cmd (struct parameters & a)
+*    Set motor current limit from either source without checking for addressed board
+*/
 void    i_cmd (struct parameters & a)
 {
-//    if  (a.respond)
-//        a.com->printf   ("In setI, setting I to %.2f\r\n", a.dbl[0]);
-    setI   (a.dbl[0] / 100.0);
+    MotorA.set_I_limit  (a.dbl[0] / 100.0);
+    MotorB.set_I_limit  (a.dbl[0] / 100.0);
 }
 
-void    kd_cmd (struct parameters & a)  //  kick the watchdog
+/**
+*void    kd_cmd (struct parameters & a)  //  kick and enable the watch dog
+*
+*/
+void    kd_cmd (struct parameters & a)  //  kick the watchdog. Reached from TS or pc.
 {
-    WatchDog = WATCHDOG_RELOAD + (I_Am() & 0x0f);
-//    a.com->printf ("Poked %d up Dog\r\n", WatchDog);
+    WatchDog = WATCHDOG_RELOAD + (mode.rd(BOARD_ID) & 0x0f);   //  Reload watchdog timeout. Counted down @ 8Hz
+    WatchDogEnable = true;                          //  Receipt of this command sufficient to enable watchdog
 }
 
-void    who_cmd (struct parameters & a)
+/**
+*void    who_cmd (struct parameters & a)     //  Reachable always from pc. Only addressed board responds to TS
+*
+*   When using STM3_ESC boards together with 'Brute Touch Screen Controller', controller needs to identify number and identity
+*   of all connected STM3_ESC boards. To do this the Touch Screen issues '0who', '1who' ... '9who' allowing time between each
+*   for an identified STM3_ESC to respond with 'who7' (if it was number 7) without causing contention of paralleled serial opto isolated bus
+*/
+void    who_cmd (struct parameters & a)     //  Reachable always from pc. Only addressed board responds to TS
 {
-    int i = I_Am    ();
-    if  (I_Am() == a.target_unit)
-        a.com->printf ("who%c\r\n", a.target_unit);
+    if  (a.source == SOURCE_PC || mode.rd(BOARD_ID) == a.target_unit)
+        a.com->printf ("who%c\r%s", mode.rd(BOARD_ID), a.source == SOURCE_PC ? "\n" : "");
 }
 
-extern  void    rcin_report ()  ;
+/**
+*void    rcin_pccmd (struct parameters & a)
+*
+*   For test, reports to pc terminal info about radio control input channels
+*/
 void    rcin_pccmd (struct parameters & a)
 {
     rcin_report ();
 }
 
-struct kb_command  {
-    const char * cmd_word;         //  points to text e.g. "menu"
-    const char * explan;
-    void (*f)(struct parameters &);   //  points to function
-}  ;
+void    scmd (struct parameters & a)    //  filter coefficient fiddler
+{
+    switch  ((int)a.dbl[0]) {
+        case    1:
+            MotorA.s[1] = MotorB.s[1] = a.dbl[1];
+            break;
+        case    2:
+            MotorA.s[2] = MotorB.s[2] = a.dbl[1];
+            break;
+        case    3:
+            MotorA.s[3] = MotorB.s[3] = a.dbl[1];
+            break;
+        case    4:
+            MotorA.s[4] = MotorB.s[4] = a.dbl[1];
+            break;
+        case    5:
+            MotorA.set_speed    (a.dbl[1]);
+            MotorB.set_speed    (a.dbl[1]);
+            break;
+        default:
+            pc.printf   ("Wrong use of scmd %f\r\n", a.dbl[0]);
+    }
+    pc.printf   ("Filter Coeffs 1 to 4\r\n");
+    pc.printf   ("1 %.3f\tPscale 0.01-0.5\r\n",     MotorA.s[1]);
+    pc.printf   ("2 %.3f\tP_gain 1.0-1000.0\r\n",   MotorA.s[2]);
+    pc.printf   ("3 %.3f\tDscale 0.01-0.5\r\n",     MotorA.s[3]);
+    pc.printf   ("4 %.3f\tD_gain 1.0-1000.0\r\n",   MotorA.s[4]);
+    pc.printf   ("5 Set target_speed\r\n");
+}
+
+    struct kb_command  {    //  Commands tabulated as list of these structures as seen below
+    const char * cmd_word;              //  points to text e.g. "menu"
+    const char * explan;                //  very brief explanation or clue as to purpose of function
+    void (*f)(struct parameters &);     //  points to function
+}  ;                                    //  Positioned in code here as knowledge needed by following menucmd
+
+/**
+*   void    menucmd (struct parameters & a)
+*
+*   List available terminal commands to pc terminal. No sense in touch screen using this
+*/
+void    menucmd (struct parameters & a)
+{
+    if  (a.respond) {
+        a.com->printf("\r\n\nDual BLDC ESC type STM3 2018\r\nAt menucmd function - listing commands, source %s:-\r\n", a.source == SOURCE_PC ? "PC" : "TS");
+        for(int i = 0; i < a.numof_menu_items; i++)
+            a.com->printf("[%s]\t\t%s\r\n", a.command_list[i].cmd_word, a.command_list[i].explan);
+        a.com->printf("End of List of Commands\r\n");
+    }
+}
+
+/********************** END OF COMMAND LINE INTERPRETER COMMANDS *************************************/
 
 
 /**
-struct  kb_command const loco_command_list[] = {
-List of commands accepted from external controller through opto isolated com port 9600, 8,n,1
+*   struct  kb_command const loco_command_list[] = {
+*   List of commands accepted from external controller through opto isolated com port 19200, 8,n,1
 */
-struct  kb_command const loco_command_list[] = {
-    {"ls", "Lists available commands", menucmd},
-    {"?", "Lists available commands, same as ls", menucmd},
+struct  kb_command const loco_command_list[] = {    //  For comms between STM3_ESC and 'Brute Touch Screen Controller'
+    //  ***** Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response *****
     {"fw", "forward", fw_cmd},
     {"re", "reverse", re_cmd},
     {"rb", "regen brake 0 to 99 %", rb_cmd},
@@ -302,23 +449,19 @@
     {"v", "set motors V percent RANGE 0 to 100", v_cmd},
     {"i", "set motors I percent RANGE 0 to 100", i_cmd},
     {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd},
+    {"kd", "kick the dog, reloads WatchDog", kd_cmd},
+    //  ***** Endof Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response *****
+
+    //  ***** Following are rx'd requests for serial response from addressed STM3_ESC only
+    {"?v", "Report system bus voltage", sysV_report},
+    {"?i", "Report motor both currents", sysI_report},
     {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd},
-    {"mode", "read or set params in eeprom", mode_cmd},
-    {"erase", "set eeprom contents to all 0xff", erase_cmd},
     {"tem", "report temperature", temperature_cmd},
-    {"kd", "kick the dog, reloads WatchDog", kd_cmd},
-    {"wden", "enable watchdog if modes allow", wden_lococmd},
-    {"wddi", "disable watchdog always", wddi_lococmd},
-    {"rpm", "read motor pair speeds", rpm_cmd},
     {"mph", "read loco speed miles per hour", mph_cmd},
-    {"rvi", "read most recent values sent to pwms", rvi_cmd},
-    {"rdi", "read motor currents and power voltage", rdi_cmd},
-    {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd},    //  OBSOLETE, replaced by 'gbb'
-    {"gbb", "get bogie bytes from eeprom and report", gbb_cmd},
-    {"nu", "do nothing", null_cmd},
-};
-
-//const int numof_loco_menu_items = sizeof(loco_command_list) / sizeof(kb_command);
+//    {"rvi", "read most recent values sent to pwms", rvi_cmd},
+//    {"rdi", "read motor currents and power voltage", rdi_cmd},
+    //  ***** Endof
+}   ;
 
 
 /**
@@ -328,7 +471,10 @@
 struct  kb_command const pc_command_list[] = {
     {"ls", "Lists available commands", menucmd},
     {"?", "Lists available commands, same as ls", menucmd},
+#ifdef  USING_DC_MOTORS
     {"mtypes", "report types of motors found", mt_cmd},
+#endif
+    {"s","1-4, filter param", scmd},
     {"pot", "read drivers control pot", pot_cmd},
     {"fw", "forward", fw_cmd},
     {"re", "reverse", re_cmd},
@@ -337,195 +483,120 @@
     {"v", "set motors V percent RANGE 0 to 100", v_cmd},
     {"i", "set motors I percent RANGE 0 to 100", i_cmd},
     {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd},
+    {"?v", "Report system bus voltage", sysV_report},
+    {"?i", "Report motor both currents", sysI_report},
     {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd},
-    {"mode", "read or set params in eeprom", mode_cmd},
-    {"erase", "set eeprom contents to all 0xff", erase_cmd},
-    {"tem", "report temperature", temperature_cmd},
+    {"mode", "read or set params in eeprom", mode19_cmd},                                 //  Big change Jan 2019
+//    {"erase", "set eeprom contents to all 0xff", erase_cmd},
+    {"tem", "report temperature", temperature_cmd},                                     //  Reports -50 when sensor not fitted
     {"kd", "kick the dog, reloads WatchDog", kd_cmd},
-    {"wden", "enable watchdog if modes allow", wden_pccmd},
-    {"wddi", "disable watchdog always", wddi_pccmd},
+    {"ver", "Version", ver_cmd},
     {"rcin", "Report Radio Control Input stuff", rcin_pccmd},
     {"rpm", "read motor pair speeds", rpm_cmd},
     {"mph", "read loco speed miles per hour", mph_cmd},
     {"rvi", "read most recent values sent to pwms", rvi_cmd},
     {"rdi", "read motor currents and power voltage", rdi_cmd},
-    {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd},
-    {"gbb", "get bogie bytes from eeprom and report", gbb_cmd},    //  OBSOLETE, replaced by 'gbb'
+//    {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd},
+//    {"gbb", "get bogie bytes from eeprom and report", gbb_cmd},    //  OBSOLETE, replaced by 'gbb'
     {"nu", "do nothing", null_cmd},
-};
+}   ;
 
-void    setup_comms ()  {
-    pccom.com = & pc;
-    pccom.command_list = pc_command_list;
-    pccom.numof_menu_items = sizeof(pc_command_list) / sizeof(kb_command);
-    pccom.cl_index  = 0;
-    pccom.gp_i      = 0;    //  general puropse integer, not used to 30/4/2018
-    pccom.resp_always   = true;
-    lococom.com = & com2;
-    lococom.command_list = loco_command_list;
-    lococom.numof_menu_items = sizeof(loco_command_list) / sizeof(kb_command);
-    lococom.cl_index    = 0;
-    lococom.gp_i        = 0;    //  general puropse integer, toggles 0 / 1 to best guess source of rpm
-    lococom.resp_always = false;
-}
-
-
-void    menucmd (struct parameters & a)
-{
-    if  (a.respond) {
-        a.com->printf("\r\n\nDual BLDC ESC type STM3 2018\r\nAt menucmd function - listing commands:-\r\n");
-        for(int i = 0; i < a.numof_menu_items; i++)
-            a.com->printf("[%s]\t\t%s\r\n", a.command_list[i].cmd_word, a.command_list[i].explan);
-        a.com->printf("End of List of Commands\r\n");
-    }
-}
+//    cli_2019    (BufferedSerial * comport, kb_command const * list, int list_len, int source)  {
+/**
+*   cli_2019    pcc (&pc,   pc_command_list,    sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC)  ;
+*   cli_2019    tsc (&com2, loco_command_list,  sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS)  ;
+*
+*   Instantiate two Command Line Interpreters, one for pc terminal and one for touch screen controller
+*/
+cli_2019    pcc (&pc,   pc_command_list,    sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC)  ;
+cli_2019    tsc (&com2, loco_command_list,  sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS)  ;
 
 /*
 New - March 2018
-Using opto isolated serial port, paralleled up using same pair to multiple boards running this code.
+Using opto isolated serial port, paralleled up using same pair to multiple STM3_ESC boards running this code.
 New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to.
 Commands without prefix digit - broadcast to all units, all to obey but none to respond.
 Only units recognising its address from prefix digit may respond. This avoids bus contention.
 But for BROADCAST commands, '0' may respond on behalf of the group
 */
-//void    command_line_interpreter    (void const *argument)
-void    cli_core    (struct parameters & a) {
-    const int MAX_CMD_LEN = 180;
-    int ch, IAm = I_Am();
+
+/**
+*   void    cli_2019::test ()  {
+*
+*   Daft check that class instantiation worked
+*/
+void    cli_2019::test ()  {
+    pc.printf   ("At cli2019::test, source %d len %d,\r\n", a.source, a.numof_menu_items);
+}
+
+/**
+*   void    cli_2019::core ()  {    
+*
+*   Command Line Interpreter.
+*   This to be called every few milli secs from main programme loop.
+*   Reads any rx'd chars into command line buffer, returns when serial buffer empty.
+*   If last char rx'd war '\r' end of text delimiter, apt command_list is searched for a matched command in command line
+*   If matched command found, apt function is executed.
+*   Parameters available to functions from 'parameters' struct.
+*/
+void    cli_2019::core ()  {    
+    int ch, IAm = mode.rd(BOARD_ID);
     char * pEnd;//, * cmd_line_ptr;
     while  (a.com->readable()) {
         ch = a.com->getc();
-        if  (a.cl_index > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
+        if  (clindex > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
+            ESC_Error.set   (FAULT_COM_LINE_LEN, 1);                      //  Set FAULT_EEPROM bit 0 if 24LC64 problem
             a.com->printf   ("Error!! Stupidly long cmd line\r\n");
-            a.cl_index = 0;
+            clindex = 0;
         }
         if(ch != '\r')  {   //  was this the 'Enter' key?
             if  (ch != '\n')       //  Ignore line feeds
-                a.cmd_line[a.cl_index++] = ch;  //  added char to command being assembled
+                cmdline[clindex++] = ch;  //  added char to command being assembled
         }
         else    {   //  key was CR, may or may not be command to lookup
             a.target_unit = BROADCAST;    //  Set to BROADCAST default once found command line '\r'
-            a.cmd_line_ptr = a.cmd_line;
-            a.cmd_line[a.cl_index] = 0; //  null terminate command string
-            if(a.cl_index)    {   //  If have got some chars to lookup
+            cmdline_ptr = cmdline;
+            cmdline[clindex] = 0; //  null terminate command string
+            if(clindex)    {   //  If have got some chars to lookup
                 int i, wrdlen;
-                if  (isdigit(a.cmd_line[0]))  {   //  Look for command with prefix digit
-                    a.cmd_line_ptr++;     //  point past identified digit prefix
-                    a.target_unit = a.cmd_line[0];  //  '0' to '9'
+                if  (isdigit(cmdline[0]))  {   //  Look for command with prefix digit
+                    cmdline_ptr++;     //  point past identified digit prefix
+                    a.target_unit = cmdline[0];  //  '0' to '9'
                     //com->printf ("Got prefix %c\r\n", cmd_line[0]);
                 }
                 for (i = 0; i < a.numof_menu_items; i++)   {   //  Look for input match in command list
-                    wrdlen = strlen(a.command_list[i].cmd_word);
-                    if(strncmp(a.command_list[i].cmd_word, a.cmd_line_ptr, wrdlen) == 0 && !isalpha(a.cmd_line_ptr[wrdlen]))  {   //  If match found
+                    wrdlen = strlen(commandlist[i].cmd_word);
+                    if(strncmp(commandlist[i].cmd_word, cmdline_ptr, wrdlen) == 0 && !isalpha(cmdline_ptr[wrdlen]))  {   //  If match found
                         for (int k = 0; k < MAX_PARAMS; k++)    {
                             a.dbl[k] = 0.0;
                         }
                         a.position_in_list = i;
                         a.numof_dbls = 0;
-                        pEnd = a.cmd_line_ptr + wrdlen;
+                        pEnd = cmdline_ptr + wrdlen;
                         while   (*pEnd)  {          //  Assemble all numerics as doubles
                             a.dbl[a.numof_dbls++] = strtod    (pEnd, &pEnd);
                             while   (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd)  {
                                 pEnd++;
                             }
                         }
-                        //com->printf   ("\r\n");   //  Not allowed as many may output this.
-                        //for (int k = 0; k < param_block.numof_dbls; k++)
-                        //    com->printf   ("Read %.3f\r\n", param_block.dbl[k]);
-//                            param_block.times[i] = clock();
-//                        a.respond = false;
                         a.respond = a.resp_always;
                         if  (((a.target_unit == BROADCAST) && (IAm == '0')) || (IAm == a.target_unit))
                             a.respond = true; //  sorted 26/4/18
                         //  All boards to obey BROADCAST command, only specific board to obey number prefixed command
                         if  ((a.target_unit == BROADCAST) || (IAm == a.target_unit))
-                            a.command_list[i].f(a);   //  execute command if addressed to this unit
+                            commandlist[i].f(a);   //  execute command if addressed to this unit
                         i = a.numof_menu_items + 1;    //  to exit for loop
                     }   //  end of match found
                 }       // End of for numof_menu_items
-                if(i == a.numof_menu_items)
-                    a.com->printf("No Match Found for CMD [%s]\r\n", a.cmd_line);
+                if(i == a.numof_menu_items) {
+//                    a.com->printf("No Match Found for CMD [%s]\r\n", cmdline);
+                    pc.printf("No Match Found for CMD [%s]\r\n", cmdline);
+                    ESC_Error.set   (FAULT_COM_LINE_NOMATCH, 1);                      //  Set FAULT_EEPROM bit 0 if 24LC64 problem
+                }
             }           //  End of If have got some chars to lookup
-            //com->printf("\r\n>");
-            a.cl_index = 0;
-        }               // End of else key was CR, may or may not be command to lookup
-    }                   //  End of while (com->readable())
-}
-
-void    command_line_interpreter_pc    ()   {
-    cli_core    (pccom);
-}
-void    command_line_interpreter_loco    () {
-    cli_core    (lococom);
-}
-
-void    command_line_interpreter    ()
-{
-/*    const int MAX_CMD_LEN = 120;
-    static  char    cmd_line[MAX_CMD_LEN + 4];
-    static  int     cl_index = 0;
-    int ch, IAm = I_Am();
-    char * pEnd, * cmd_line_ptr;
-    static struct  parameters  param_block  ;
-    com = &com2;
-    while  (com->readable()) {
-//        ch = tolower(com->getc());
-        ch = com->getc();
-        if  (cl_index > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
-            com->printf   ("Error!! Stupidly long cmd line\r\n");
-            cl_index = 0;
-        }
-        if(ch != '\r')  //  was this the 'Enter' key?
-            cmd_line[cl_index++] = ch;  //  added char to command being assembled
-        else    {   //  key was CR, may or may not be command to lookup
-            param_block.target_unit = BROADCAST;    //  Set to BROADCAST default once found command line '\r'
-            cmd_line_ptr = cmd_line;
-            cmd_line[cl_index] = 0; //  null terminate command string
-            if(cl_index)    {   //  If have got some chars to lookup
-                int i, wrdlen;
-                if  (isdigit(cmd_line[0]))  {   //  Look for command with prefix digit
-                    cmd_line_ptr++;     //  point past identified digit prefix
-                    param_block.target_unit = cmd_line[0];  //  '0' to '9'
-                    //com->printf ("Got prefix %c\r\n", cmd_line[0]);
-                }
-                for (i = 0; i < a.numof_menu_items; i++)   {   //  Look for input match in command list
-                    wrdlen = strlen(a.command_list[i].cmd_word);
-                    if(strncmp(a.command_list[i].cmd_word, a.cmd_line_ptr, wrdlen) == 0 && !isalpha(a.cmd_line_ptr[wrdlen]))  {   //  If match found
-                        for (int k = 0; k < MAX_PARAMS; k++)    {
-                            param_block.dbl[k] = 0.0;
-                        }
-                        param_block.position_in_list = i;
-//                        param_block.last_time = clock    ();
-                        param_block.numof_dbls = 0;
-                        pEnd = cmd_line_ptr + wrdlen;
-                        while   (*pEnd)  {          //  Assemble all numerics as doubles
-                            param_block.dbl[param_block.numof_dbls++] = strtod    (pEnd, &pEnd);
-                            while   (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd)  {
-                                pEnd++;
-                            }
-                        }
-                        //com->printf   ("\r\n");   //  Not allowed as many may output this.
-                        //for (int k = 0; k < param_block.numof_dbls; k++)
-                        //    com->printf   ("Read %.3f\r\n", param_block.dbl[k]);
-//                            param_block.times[i] = clock();
-                        param_block.respond = false;
-                        if  (((param_block.target_unit == BROADCAST) && (IAm == '0')) || (IAm == param_block.target_unit))
-                            param_block.respond = true; //  sorted 26/4/18
-                        //  All boards to obey BROADCAST command, only specific board to obey number prefixed command
-                        if  ((param_block.target_unit == BROADCAST) || (IAm == param_block.target_unit))
-                            command_list[i].f(param_block);   //  execute command if addressed to this unit
-                        i = numof_menu_items + 1;    //  to exit for loop
-                    }   //  end of match found
-                }       // End of for numof_menu_items
-                if(i == numof_menu_items)
-                    com->printf("No Match Found for CMD [%s]\r\n", cmd_line);
-            }           //  End of If have got some chars to lookup
-            //com->printf("\r\n>");
-            cl_index = 0;
-        }               // End of else key was CR, may or may not be command to lookup
-    }                   //  End of while (com->readable())
-//        Thread::wait(20);  //  Using RTOS on this project
-//    }*/
-}
+            clindex = 0;
+        }       // End of else key was CR, may or may not be command to lookup
+    }           //  End of while (com->readable())
+}               //  end of command line interpreter core function