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

Files at this revision

API Documentation at this revision

Comitter:
JonFreeman
Date:
Tue Jun 05 07:19:39 2018 +0000
Parent:
5:ca86a7848d54
Child:
7:6deaeace9a3e
Commit message:
Migrating towards code for both STM32F401RET (64 pin) and STM32F446ZET7 (144 pin). Should resolve IO conflicts for larger device - getting servo ins and outs working

Changed in this revision

DualBLS.h Show annotated file Show diff for this revision Revisions of this file
cli_BLS_nortos.cpp Show annotated file Show diff for this revision Revisions of this file
cli_nortos.cpp Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/DualBLS.h	Tue May 29 16:36:34 2018 +0000
+++ b/DualBLS.h	Tue Jun 05 07:19:39 2018 +0000
@@ -21,6 +21,7 @@
 const   double      PI      = 4.0 * atan(1.0),
                     TWOPI   = 8.0 * atan(1.0);
 
+enum    {MOTADIR, MOTBDIR, GANG, SVO1, SVO2, COMM_SRC, ID, WHEELDIA, MOTPIN, WHEELGEAR}  ;  //  Identical in TS and DualBLS
 struct  optpar  {
     int min, max, def;  //  min, max, default
     const char * t;     //  description
@@ -33,6 +34,12 @@
     {0, 2, 2, "Servo2 0, 1, 2 = Not used, Input, Output"},
     {1, 5, 2, "Command 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
 }   ;
-const int    numofopts    = sizeof(option_list) / sizeof (struct optpar);
+const int    numof_eeprom_options    = sizeof(option_list) / sizeof (struct optpar);
 
+struct  single_bogie_options   {
+    char    motoradir, motorbdir, gang, svo1, svo2, comm_src, id, wheeldia, motpin, wheelgear, spare;
+}   ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cli_BLS_nortos.cpp	Tue Jun 05 07:19:39 2018 +0000
@@ -0,0 +1,334 @@
+//  DualBLS2018_03
+#include "mbed.h"
+#include "BufferedSerial.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  int WatchDog;
+
+const int   BROADCAST   = '\r';
+const   int MAX_PARAMS = 20;
+struct  parameters  {
+    int32_t position_in_list,   //  set but not used Apr 2018, contains i for i'th menu item
+//            last_time,          //  gets reading from clock() ; not known to be useful or reliable
+            numof_dbls,
+            target_unit;
+    double  dbl[MAX_PARAMS];
+    bool    respond;
+}   ;
+
+//  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    read_last_VI    (double * val)  ;   //  only for test from cli
+
+BufferedSerial * com;
+
+void    null_cmd (struct parameters & a)
+{
+    if  (a.respond) 
+        com->printf   ("At null_cmd, board ID %c, parameters : First %.3f, second %.3f\r\n", I_Am(), a.dbl[0], a.dbl[1]);
+}
+
+extern  void    mode_set   (int mode, double val)  ;   //  called from cli to set fw, re, rb, hb
+extern  void    read_supply_vi   (double * val)  ;
+
+void    rdi_cmd (struct parameters & a)  //  read motor currents
+{
+    if  (a.respond) {
+        double  r[4];
+        read_supply_vi  (r);    //  get MotorA.I.ave, MotorB.I.ave, Battery volts
+        com->printf ("rdi%.0f %.0f %.1f\r", r[0], r[1], r[2]);  //  Format good to be unpicked by cli in touch screen controller
+    }
+}
+
+void    rvi_cmd (struct parameters & a)  //  read last normalised values sent to pwms
+{
+    if  (a.respond) {
+        double  r[6];
+        read_last_VI    (r);
+        com->printf ("rvi%.2f %.2f %.2f %.2f\r", r[0], r[1], r[2], r[3]);
+    }
+}
+
+void    fw_cmd (struct parameters & a)  //  Forward command
+{
+    mode_set   (FORWARD, 0.0);
+}
+
+void    re_cmd (struct parameters & a)  //  Reverse command
+{
+    mode_set   (REVERSE, 0.0);
+}
+
+void    rb_cmd (struct parameters & a)      //  Regen brake command
+{
+    double b = a.dbl[0] / 100.0;
+//    com->printf   ("Applying brake %.3f\r\n", b);
+    mode_set   (REGENBRAKE, b);
+//    apply_brake (b);
+}
+
+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
+{
+    char    t[36];
+    for (int i = 0; i < 32; i++)
+        t[i] = 0xff;
+    for (int i = 0; i < 8191; i += 32)  {
+        com->printf (".");
+        if  (!wr_24LC64   (i, t, 32))
+            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;
+}   ;
+*/
+extern  char mode_bytes[];
+
+void    mode_cmd (struct parameters & a)       //  With no params, reads eeprom contents. With params sets eeprom contents
+{
+    if  (a.target_unit == BROADCAST) {
+//        com->printf ("At mode_cmd, can not use BROADCAST with mode_cmd\r\n");
+    } else    {
+        char    t[36];
+        com->printf ("At mode_cmd with node %d\r\n", a.target_unit);
+        rd_24LC64   (0, t, 32);
+        com->printf ("Numof params=%d\r\n", a.numof_dbls);
+        for (int i = 0; i < numof_eeprom_options; i++)
+            com->printf ("%2x\t%s\r\n", t[i], option_list[i].t);
+        if  (a.numof_dbls == 0) {   //  Read present contents, do not write
+            com->printf ("That's it\r\n");
+        } else    { //  Write new shit to eeprom
+            com->printf ("\r\n");
+            if  (a.numof_dbls != numof_eeprom_options) {
+                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;
+                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
+                        com->printf("Warning - Parameter = %d, out of range, setting to default %d\r\n", b, option_list[i].def);
+                        b = option_list[i].def;
+                    }
+                    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);
+                com->printf("Parameters set in eeprom\r\n");
+            }
+        }
+    }
+}
+/*void    coast_cmd (struct parameters & a)   {   //  Coast
+
+}
+*/
+void    hb_cmd (struct parameters & a)
+{
+    if  (a.respond) {
+        com->printf   ("numof params = %d\r\n", a.numof_dbls);
+        com->printf   ("Hand Brake : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
+    }
+    mode_set   (HANDBRAKE, 0.0);
+}
+
+extern  uint32_t    last_temp_count;
+void    temperature_cmd  (struct parameters & a)  {
+    if  (a.respond) {
+        com->printf ("tem%c %d\r\n", mode_bytes[ID], (last_temp_count / 16) - 50);
+    }
+}
+
+void    bogie_constants_report_cmd  (struct parameters & a)  {
+    if  (a.respond) {
+        com->printf ("bc%c %d %d %d\r\n", mode_bytes[ID], mode_bytes[WHEELDIA], mode_bytes[MOTPIN], mode_bytes[WHEELGEAR]);
+    }
+}
+
+extern  void    read_RPM    (uint32_t * dest)  ;
+void    rpm_cmd (struct parameters & a) //  to report e.g. RPM 1000 1000 ; speed for both motors
+{
+    if  (a.respond) {
+        uint32_t dest[3];
+        read_RPM    (dest);
+        com->printf  ("rpm%d %d\r", dest[0], dest[1]);
+    }
+}
+
+void    menucmd (struct parameters & a);
+
+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);
+}
+
+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);
+}
+
+void    i_cmd (struct parameters & a)
+{
+//    if  (a.respond)
+//        com->printf   ("In setI, setting I to %.2f\r\n", a.dbl[0]);
+    setI   (a.dbl[0] / 100.0);
+}
+
+void    kd_cmd (struct parameters & a)  //  kick the watchdog
+{
+    WatchDog = WATCHDOG_RELOAD + (I_Am() & 0x0f);
+//    com->printf ("Poked %d up Dog\r\n", WatchDog);
+}
+
+void    who_cmd (struct parameters & a)
+{
+    int i = I_Am    ();
+    if  (I_Am() == a.target_unit)
+        com->printf ("who%c\r\n", a.target_unit);
+}
+
+struct kb_command  {
+    const char * cmd_word;         //  points to text e.g. "menu"
+    const char * explan;
+    void (*f)(struct parameters &);   //  points to function
+}  ;
+
+struct  kb_command const command_list[] = {
+    {"ls", "Lists available commands", menucmd},
+    {"?", "Lists available commands, same as ls", menucmd},
+    {"fw", "forward", fw_cmd},
+    {"re", "reverse", re_cmd},
+    {"rb", "regen brake 0 to 99 %", rb_cmd},
+    {"hb", "hand brake", hb_cmd},
+    {"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},
+    {"who", "search for connected units, e.g. 3who returs 'Hi there' 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},
+    {"rpm", "read motor pair speeds", rpm_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},
+    {"nu", "do nothing", null_cmd},
+};
+
+const int numof_menu_items = sizeof(command_list) / sizeof(kb_command);
+void    menucmd (struct parameters & a)
+{
+    if  (a.respond) {
+        com->printf("\r\n\nDouble Brushless Motor Driver 2018\r\nAt menucmd function - listing commands:-\r\n");
+        for(int i = 0; i < numof_menu_items; i++)
+            com->printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan);
+        com->printf("End of List of Commands\r\n");
+    }
+}
+
+/*
+New - March 2018
+Using opto isolated serial port, paralleled up using same pair to multiple 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    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 < numof_menu_items; i++)   {   //  Look for input match in command list
+                    wrdlen = strlen(command_list[i].cmd_word);
+                    if(strncmp(command_list[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(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
+//    }
+}
+
+
--- a/cli_nortos.cpp	Tue May 29 16:36:34 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,313 +0,0 @@
-//  DualBLS2018_03
-#include "mbed.h"
-#include "BufferedSerial.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  int WatchDog;
-
-const int   BROADCAST   = '\r';
-const   int MAX_PARAMS = 20;
-struct  parameters  {
-    int32_t position_in_list,   //  set but not used Apr 2018, contains i for i'th menu item
-//            last_time,          //  gets reading from clock() ; not known to be useful or reliable
-            numof_dbls,
-            target_unit;
-    double  dbl[MAX_PARAMS];
-    bool    respond;
-}   ;
-
-//  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    read_last_VI    (double * val)  ;   //  only for test from cli
-
-BufferedSerial * com;
-
-void    null_cmd (struct parameters & a)
-{
-    if  (a.respond) 
-        com->printf   ("At null_cmd, board ID %c, parameters : First %.3f, second %.3f\r\n", I_Am(), a.dbl[0], a.dbl[1]);
-}
-
-extern  void    mode_set   (int mode, double val)  ;
-extern  void    read_supply_vi   (double * val)  ;
-
-void    rdi_cmd (struct parameters & a)  //  read motor currents
-{
-    if  (a.respond) {
-        double  r[4];
-        read_supply_vi  (r);    //  get MotorA.I.ave, MotorB.I.ave, Battery volts
-        com->printf ("rdi%.0f %.0f %.1f\r", r[0], r[1], r[2]);  //  Format good to be unpicked by cli in touch screen controller
-    }
-}
-
-void    rvi_cmd (struct parameters & a)  //  read last normalised values sent to pwms
-{
-    if  (a.respond) {
-        double  r[6];
-        read_last_VI    (r);
-        com->printf ("rvi%.2f %.2f %.2f %.2f\r", r[0], r[1], r[2], r[3]);
-    }
-}
-
-void    fw_cmd (struct parameters & a)  //  Forward command
-{
-    mode_set   (FORWARD, 0.0);
-}
-
-void    re_cmd (struct parameters & a)  //  Reverse command
-{
-    mode_set   (REVERSE, 0.0);
-}
-
-void    rb_cmd (struct parameters & a)      //  Regen brake command
-{
-    double b = a.dbl[0] / 100.0;
-//    com->printf   ("Applying brake %.3f\r\n", b);
-    mode_set   (REGENBRAKE, b);
-//    apply_brake (b);
-}
-
-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
-{
-    char    t[36];
-    for (int i = 0; i < 32; i++)
-        t[i] = 0xff;
-    for (int i = 0; i < 8191; i += 32)  {
-        com->printf (".");
-        if  (!wr_24LC64   (i, t, 32))
-            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
-            last;
-}   ;
-*/
-
-void    mode_cmd (struct parameters & a)       //  With no params, reads eeprom contents. With params sets eeprom contents
-{
-    if  (a.target_unit == BROADCAST) {
-//        com->printf ("At mode_cmd, can not use BROADCAST with mode_cmd\r\n");
-    } else    {
-        char    t[36];
-        com->printf ("At mode_cmd with node %d\r\n", a.target_unit);
-        rd_24LC64   (0, t, 32);
-        com->printf ("Numof params=%d\r\n", a.numof_dbls);
-        for (int i = 0; i < numofopts; i++)
-            com->printf ("%2x\t%s\r\n", t[i], option_list[i].t);
-        if  (a.numof_dbls == 0) {   //  Read present contents, do not write
-            com->printf ("That's it\r\n");
-        } else    { //  Write new shit to eeprom
-            com->printf ("\r\n");
-            if  (a.numof_dbls != numofopts) {
-                com->printf ("params required = %d, you offered %d\r\n", numofopts, a.numof_dbls);
-            } else    { //  Have been passed correct number of parameters
-                int b;
-                com->printf("Ready to write params to eeprom\r\n");
-                for (int i = 0; i < numofopts; 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
-                        com->printf("Warning - Parameter = %d, out of range, setting to default %d\r\n", b, option_list[i].def);
-                        b = option_list[i].def;
-                    }
-                    com->printf ("0x%2x\t%s\r\n", (t[i] = b), option_list[i].t);
-                }
-                wr_24LC64   (0, t, numofopts);
-                com->printf("Parameters set in eeprom\r\n");
-            }
-        }
-    }
-}
-/*void    coast_cmd (struct parameters & a)   {   //  Coast
-
-}
-*/
-void    hb_cmd (struct parameters & a)
-{
-    if  (a.respond) {
-        com->printf   ("numof params = %d\r\n", a.numof_dbls);
-        com->printf   ("Hand Brake : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
-    }
-    mode_set   (HANDBRAKE, 0.0);
-}
-
-extern  void    read_RPM    (uint32_t * dest)  ;
-void    rpm_cmd (struct parameters & a) //  to report e.g. RPM 1000 1000 ; speed for both motors
-{
-    if  (a.respond) {
-        uint32_t dest[3];
-        read_RPM    (dest);
-        com->printf  ("rpm%d %d\r", dest[0], dest[1]);
-    }
-}
-
-void    menucmd (struct parameters & a);
-
-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);
-}
-
-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);
-}
-
-void    i_cmd (struct parameters & a)
-{
-//    if  (a.respond)
-//        com->printf   ("In setI, setting I to %.2f\r\n", a.dbl[0]);
-    setI   (a.dbl[0] / 100.0);
-}
-
-void    kd_cmd (struct parameters & a)  //  kick the watchdog
-{
-    WatchDog = WATCHDOG_RELOAD + (I_Am() & 0x0f);
-//    com->printf ("Poked %d up Dog\r\n", WatchDog);
-}
-
-void    who_cmd (struct parameters & a)
-{
-    int i = I_Am    ();
-    if  (I_Am() == a.target_unit)
-        com->printf ("Hi there, I am %c\r\n", a.target_unit);
-}
-
-struct kb_command  {
-    const char * cmd_word;         //  points to text e.g. "menu"
-    const char * explan;
-    void (*f)(struct parameters &);   //  points to function
-}  ;
-
-struct  kb_command const command_list[] = {
-    {"ls", "Lists available commands", menucmd},
-    {"?", "Lists available commands, same as ls", menucmd},
-    {"fw", "forward", fw_cmd},
-    {"re", "reverse", re_cmd},
-    {"rb", "regen brake 0 to 99 %", rb_cmd},
-    {"hb", "hand brake", hb_cmd},
-    {"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},
-    {"who", "search for connected units, e.g. 3who returs 'Hi there' if found", who_cmd},
-    {"mode", "read or set params in eeprom", mode_cmd},
-    {"erase", "set eeprom contents to all 0xff", erase_cmd},
-    {"kd", "kick the dog, reloads WatchDog", kd_cmd},
-    {"rpm", "read motor pair speeds", rpm_cmd},
-    {"rvi", "read most recent values sent to pwms", rvi_cmd},
-    {"rdi", "read motor currents and power voltage", rdi_cmd},
-    {"nu", "do nothing", null_cmd},
-};
-
-const int numof_menu_items = sizeof(command_list) / sizeof(kb_command);
-void    menucmd (struct parameters & a)
-{
-    if  (a.respond) {
-        com->printf("\r\n\nDouble Brushless Motor Driver 2018\r\nAt menucmd function - listing commands:-\r\n");
-        for(int i = 0; i < numof_menu_items; i++)
-            com->printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan);
-        com->printf("End of List of Commands\r\n");
-    }
-}
-
-/*
-New - March 2018
-Using opto isolated serial port, paralleled up using same pair to multiple 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    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 < numof_menu_items; i++)   {   //  Look for input match in command list
-                    wrdlen = strlen(command_list[i].cmd_word);
-                    if(strncmp(command_list[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(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
-//    }
-}
-
-
--- a/main.cpp	Tue May 29 16:36:34 2018 +0000
+++ b/main.cpp	Tue Jun 05 07:19:39 2018 +0000
@@ -6,12 +6,12 @@
 
 /*
 New 29th May 2018 - YET TO CODE FOR - Fwd/Rev line from possible remote hand control box has signal routed to T5
-                Also new LMT01 temperature sensor routed to T1
+                Also new LMT01 temperature sensor routed to T1 - and rerouted to PC_13 at InterruptIn on T1 (ports A and B I think) not workable
 */
 
 
 /*  STM32F401RE - compile using NUCLEO-F401RE
-//  PROJECT -   Dual Brushless Motor Controller -   Jon Freeman     April 2018.
+//  PROJECT -   Dual Brushless Motor Controller -   Jon Freeman     June 2018.
 
 AnalogIn to read each motor current
 
@@ -28,6 +28,8 @@
 
 
 */
+//#if defined (TARGET_NUCLEO_F446ZE)
+#if defined (TARGET_NUCLEO_F401RE)
 
 //  Hoped to select servo functions from user info stored on EEROM. Too difficult. Do not define servo as in and out
 
@@ -80,7 +82,11 @@
 PortOut MotB    (PortB, PORT_B_MASK);
 
 //  Pin 1   VBAT    NET +3V3
-DigitalIn   J3         (PC_13, PullUp);//  Pin 2   Jumper pulls to GND, R floats Hi
+
+//DigitalIn   J3         (PC_13, PullUp);//  Pin 2   Jumper pulls to GND, R floats Hi
+InterruptIn   Temperature_pin   (PC_13);//  Pin 2   June 2018 - taken for temperature sensor - hard wired to T1 due to wrong thought T1 could be InterruptIn
+
+
 //  Pin 3   PC14-OSC32_IN   NET O32I
 //  Pin 4   PC15-OSC32_OUT  NET O32O
 //  Pin 5   PH0-OSC_IN      NET PH1
@@ -132,7 +138,15 @@
 //BufferedSerial  extra_ser   (PA_11, PA_12);    //  Pins 44, 45  tx, rx to XBee module
 DigitalOut  T2  (PA_11);    //  Pin 44
 // was DigitalOut  T1  (PA_12);    //  Pin 45
-InterruptIn T1  (PA_12);    //  Pin 45 now input counting pulses from LMT01 temperature sensor
+
+
+//InterruptIn T1  (PA_12);    //  Pin 45 now input counting pulses from LMT01 temperature sensor
+//  InterruptIn DOES NOT WORK ON PA_12. Boards are being made, will have to wire link PA12 to PC13
+DigitalIn   T1    (PA_12);
+////InterruptIn T1  (PC_13);    //  Pin 45 now input counting pulses from LMT01 temperature sensor
+
+
+
 //  Pin 46  SWDIO
 //  Pin 47  VSS
 //  Pin 48  VDD
@@ -160,7 +174,9 @@
 //  Pin 64  VDD
 //  SYSTEM CONSTANTS
 
-
+#endif
+#if defined (TARGET_NUCLEO_F446ZE)
+#endif
 /*  Global variable declarations */
 volatile    uint32_t    fast_sys_timer      = 0;    //  gets incremented by our Ticker ISR every VOLTAGE_READ_INTERVAL_US
 int         WatchDog    = WATCHDOG_RELOAD + 80; //  Allow extra few seconds at powerup
@@ -171,13 +187,31 @@
 int         IAm;
 bool        loop_flag   = false;    //  made true in ISR_loop_timer, picked up and made false again in main programme loop
 bool        flag_8Hz    = false;    //  As loop_flag but repeats 8 times per sec
+bool        temp_sensor_exists = false;
+char        mode_bytes[36];
 
+uint32_t    temp_sensor_count = 0,  //  incremented by every rising edge from LMT01
+            last_temp_count = 0;  //  global updated approx every 100ms after each LMT01 conversion completes
+//    struct  single_bogie_options    bogie;    
 /*  End of Global variable declarations */
 
 Ticker  tick_vread;     //  Device to cause periodic interrupts, used to time voltage readings etc
 Ticker  loop_timer;     //  Device to cause periodic interrupts, used to sync iterations of main programme loop
+Ticker  temperature_find_ticker;
+Timer   temperature_timer;
 
 //  Interrupt Service Routines
+void    ISR_temperature_find_ticker ()  {   //  every 960 us, i.e. slightly faster than once per milli sec
+    static  bool    readflag = false;
+    int t = temperature_timer.read_ms   ();
+    if  ((t == 5) && (!readflag))    {
+        last_temp_count = temp_sensor_count;
+        temp_sensor_count = 0;
+        readflag = true;
+    }
+    if  (t == 6)
+        readflag = false;
+}
 
 /** void    ISR_loop_timer  ()
 *   This ISR responds to Ticker interrupts at a rate of (probably) 32 times per second (check from constant declarations above)
@@ -240,7 +274,7 @@
     return  rx_active;
 }
 
-void    RControl_In::rise    ()
+void    RControl_In::rise    ()     //  These may not work as use of PortB as port may bugger InterruptIn use
 {
     t.stop   ();
     period_us = t.read_us    ();
@@ -505,11 +539,14 @@
     Hindex[1] = Hindex[0];
 }
 
-    uint32_t    temp_sensor_count = 0;  //  global
-    bool        temp_count_in_progress = false;
 
-void    temp_sensor_isr ()  {   //  got rising edge from LMT01
+void    temp_sensor_isr ()  {   //  got rising edge from LMT01. ALMOST CERTAIN this misses some
+    int t = temperature_timer.read_us   (); //  Must be being overrun by something, most likely culprit A-D reading ?
+    temperature_timer.reset ();
     temp_sensor_count++;
+    if  (t > 18)            //  Yes proved some interrupts get missed, this fixes temperature reading
+        temp_sensor_count++;
+//    T2 = !T2;   //  scope hanger
 }
 
 void    MAH_isr    ()
@@ -576,29 +613,6 @@
     d[3]    = MotorB.last_I;
 }
 
-/*void    sincostest  ()  {
-    sinv = sin(angle);  //  to set speed and direction of MotorA
-    cosv = cos(angle);  //  to set speed and direction of MotorB
-        Servos[0]->write  ((sinv + 1.0) / 2.0);
-        Servos[1]->write  ((cosv + 1.0) / 2.0);
-    angle += angle_step;
-    if  (angle > TWOPI)
-        angle -= TWOPI;
-    if  (sinv > 0.0)
-        MotorA.set_mode (FORWARD);
-    else    {
-        MotorA.set_mode (REVERSE);
-        sinv = -sinv;
-    }
-    MotorA.set_V_limit  (0.01 + (sinv / 1.3));
-    if  (cosv > 0.0)
-        MotorB.set_mode (FORWARD);
-    else    {
-        MotorB.set_mode (REVERSE);
-        cosv = -cosv;
-    }
-    MotorB.set_V_limit  (0.01 + (cosv / 1.3));
-}*/
 
 /**
 void    AtoD_reader ()  //  Call to here every VOLTAGE_READ_INTERVAL_US    = 50 once loop responds to flag set in isr
@@ -606,17 +620,8 @@
 */
 void    AtoD_reader ()  //  Call to here every VOLTAGE_READ_INTERVAL_US    = 50 once loop responds to flag set in isr
 {
-    static uint32_t i = 0, tab_ptr = 0, local_temperature_count = 0;
+    static uint32_t i = 0, tab_ptr = 0;
 
-//    sincostest  ();
-//    uint32_t    temp_sensor_count = 0;  //  global
-//    bool        temp_count_in_progress = false;
-    if  (local_temperature_count == temp_sensor_count)
-        temp_count_in_progress = false;
-    else    {
-        temp_count_in_progress = true;
-        local_temperature_count = temp_sensor_count;
-    }
     if  (MotorA.tickleon)
         MotorA.high_side_off    ();
     if  (MotorB.tickleon)
@@ -711,10 +716,6 @@
 }   ;
 */
 int I_Am    ()  {   //  Returns boards id number as ASCII char
-//    int i = J3;
-//    if  (i != 0)
-//        i = 1;
-//    return  i | '0';
     return  IAm;
 }
 
@@ -728,7 +729,8 @@
     MotPtr[0] = &MotorA;    //  Pointers to motor class objects
     MotPtr[1] = &MotorB;
     
-    T1.rise (&temp_sensor_isr);
+    Temperature_pin.fall (&temp_sensor_isr);
+    Temperature_pin.mode (PullUp);
 
     MAH1.rise   (& MAH_isr);    //  Set up interrupt vectors
     MAH1.fall   (& MAH_isr);
@@ -756,14 +758,16 @@
     //  Setup system timers to cause periodic interrupts to synchronise and automate volt and current readings, loop repeat rate etc
     tick_vread.attach_us    (&ISR_voltage_reader, VOLTAGE_READ_INTERVAL_US);    //  Start periodic interrupt generator
     loop_timer.attach_us    (&ISR_loop_timer, MAIN_LOOP_REPEAT_TIME_US);    //  Start periodic interrupt generator
+    temperature_find_ticker.attach_us   (&ISR_temperature_find_ticker, 960);
     //  Done setting up system interrupt timers
+    temperature_timer.start ();
 
-    const int TXTBUFSIZ = 36;
-    char    buff[TXTBUFSIZ];
+//    const   int TXTBUFSIZ = 36;
+//    char    buff[TXTBUFSIZ];
     pc.baud     (9600);
     com3.baud   (1200);
     com2.baud   (19200);
-    
+
     if  (check_24LC64() != 0xa0)  { //  searches for i2c devices, returns address of highest found
         pc.printf   ("Check for 24LC64 eeprom FAILED\r\n");
         com2.printf   ("Check for 24LC64 eeprom FAILED\r\n");
@@ -777,15 +781,15 @@
 //        k = rd_24LC64  (0x1240, buff, strlen(ramtst));
 //        pc.printf("Ram test returned [%s], wr ret'd [%s], rd ret'd [%s]\r\n", buff, j ? "true" : "false", k ? "true" : "false");
 //        com2.printf("Ram test returned [%s], wr ret'd [%s], rd ret'd [%s]\r\n", buff, j ? "true" : "false", k ? "true" : "false");
-        k = rd_24LC64   (0, buff, 32);
+        k = rd_24LC64   (0, mode_bytes, 32);
 //        if  (k)
 //            com2.printf ("Good read from eeprom\r\n");
         if  (!k)
             com2.printf ("Error reading from eeprom\r\n");
 
         int err = 0;
-        for (int i = 0; i < numofopts; i++) {
-            if  ((buff[i] < option_list[i].min) || (buff[i] > option_list[i].max))  {
+        for (int i = 0; i < numof_eeprom_options; i++) {
+            if  ((mode_bytes[i] < option_list[i].min) || (mode_bytes[i] > option_list[i].max))  {
                 com2.printf ("EEROM error with %s\r\n", option_list[i].t);
                 err++;
             }
@@ -794,14 +798,14 @@
         }
         IAm = '0';
         if  (err == 0)  {
-            MotorA.direction_set    (buff[0]);
-            MotorB.direction_set    (buff[1]);
-            IAm = buff[6];
+            MotorA.direction_set    (mode_bytes[MOTADIR]);
+            MotorB.direction_set    (mode_bytes[MOTBDIR]);
+            IAm = mode_bytes[ID];
         }
            //  Alternative ID 1 to 9
 //        com2.printf ("Alternative ID = 0x%2x\r\n", buff[6]);
     }
-//    T1 = 0;   Now interruptIn counting pulses from LMT01 temperature sensor
+//    T1 = 0;   Now WRONGLY hoped to be InterruptIn counting pulses from LMT01 temperature sensor
     T2 = 0; //  T2, T3, T4 As yet unused pins
     T3 = 0;
     T4 = 0;
@@ -821,6 +825,10 @@
     Servos[0] = & Servo1;
     Servo   Servo2  (PB_9)  ;
     Servos[1] = & Servo2;
+    
+    pc.printf   ("last_temp_count = %d\r\n", last_temp_count);  //  Has had time to do at least 1 conversion
+    if  ((last_temp_count > 160) && (last_temp_count < 2400))   //  in range -40 to +100 degree C
+        temp_sensor_exists  = true;
 /*
     //  Setup Complete ! Can now start main control forever loop.
     //  March 16th 2018 thoughts !!!
@@ -843,6 +851,7 @@
             break;
     }
     */
+    pc.printf   ("Ready to go!, wheel gear in position %d\r\n", WHEELGEAR);
     while   (1) {      //  Loop forever, repeats synchroised by waiting for ticker Interrupt Service Routine to set 'loop_flag' true
         while   (!loop_flag)  {         //  Most of the time is spent in this loop, repeatedly re-checking for commands from pc port
             command_line_interpreter    ()  ;   //  Proceed beyond here once loop_timer ticker ISR has set loop_flag true
@@ -866,8 +875,14 @@
             eighth_sec_count++;
             if  (eighth_sec_count > 6)    {   //  Send some status info out of serial port every second and a bit or thereabouts
                 eighth_sec_count = 0;
-            MotorA.current_calc ();     //  Updates readings in MotorA.I.min, MotorA.I.ave and MotorA.I.max
-            MotorB.current_calc ();
+                MotorA.current_calc ();     //  Updates readings in MotorA.I.min, MotorA.I.ave and MotorA.I.max
+                MotorB.current_calc ();
+                if  (temp_sensor_exists)    {
+                    double  tmprt = (double) last_temp_count;
+                    tmprt /= 16.0;
+                    tmprt -= 50.0;
+                    pc.printf   ("Temp %.2f\r\n", tmprt);
+                }
 //                com2.printf   ("V=%+.2f, Pot=%+.2f, HA %d, HB %d, IAmin %d, IAave %d, IAmax %d, IB %d, Arpm %d, Brpm %d\r\n", Read_BatteryVolts(), Read_DriverPot(), MotorA.read_Halls  (), MotorB.read_Halls  (), MotorA.I.min, MotorA.I.ave, MotorA.I.max, MotorB.I.ave, (Apps * 60) / 24, (Bpps * 60) / 24);
             }
         }   //  End of if(flag_8Hz)