Touch screen drivers control dashboard for miniature locomotive. Features meters for speed, volts, power. Switches for lights, horns. Drives multiple STM3_ESC brushless motor controllers for complete brushless loco system as used in "The Brute" - www.jons-workshop.com

Dependencies:   TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM

Files at this revision

API Documentation at this revision

Comitter:
JonFreeman
Date:
Mon Mar 04 17:47:27 2019 +0000
Parent:
13:390430631255
Commit message:
'Brute' Locomotive Touch Screen Controller - Driver's Controls; Always a 'Work In Progress', snapshot March 2019

Changed in this revision

Electric_Loco.h Show annotated file Show diff for this revision Revisions of this file
cli_TS_nortos.cpp Show annotated file Show diff for this revision Revisions of this file
error_handler.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/Electric_Loco.h	Mon Jan 14 16:51:16 2019 +0000
+++ b/Electric_Loco.h	Mon Mar 04 17:47:27 2019 +0000
@@ -37,8 +37,6 @@
 #define AMMETER_Y   202
 #define SPEEDO_X    274     //  Speedometer screen position
 #define SPEEDO_Y    135
-//#define V_A_SIZE    54      //  Size of voltmeter and ammeter
-//#define SPEEDO_SIZE 112
 
 #define V_A_SIZE    56      //  Size of voltmeter and ammeter
 #define SPEEDO_SIZE 114
@@ -127,7 +125,7 @@
     void        clr   (uint32_t)   ;
     uint32_t    read  (uint32_t)   ;
     bool        all_good    ()  ;
-    void        report_any  ()  ;
+    void        report_any  (bool)  ;
 }   ;
 
 class   command_line_interpreter_core  {
@@ -161,7 +159,7 @@
             esc_speeds[i] = 0.0;
         }
     }
-    bool    request_mph     ()  ;       //  Issue "'n'mph\r" to one particular STM3_ESC board to request RPM   22/06/2018
+    bool    request_mph     ()  ;       //  Issue "'n'mph\r" to one particular STM3_ESC board to request MPH   22/06/2018
     void    mph_update      (double)  ; //  touched 08/01/2019
     void    set_board_ID    (int)   ;   //  called in response to 'whon' coming back from a STM3_ESC
     void    search_for_escs ()  ;       //  one-off call during startup to identify all connected STM3_ESCs
--- a/cli_TS_nortos.cpp	Mon Jan 14 16:51:16 2019 +0000
+++ b/cli_TS_nortos.cpp	Mon Mar 04 17:47:27 2019 +0000
@@ -102,10 +102,10 @@
         count++;
     pc.printf   ("Board Count = %d\r\n", count);
     if  (count) {
-        pc.printf   ("Boards found ^");
+        pc.printf   ("Boards found [");
         for (int i = 0; i < count; i++)
             pc.printf   ("%c ", boards[i]);
-        pc.printf   ("\r\n");
+        pc.printf   ("]\r\n");
     }
     else
         pc.printf   ("No STM3_ESC boards found\r\n");
@@ -127,28 +127,52 @@
     pc.printf   ("ver_req_cmd not yet implemented\r\n");
 }
 
+void    queryv  (struct parameters & a) {   //  Handle response from ESC resulting from prior TSC "n?v\r" sent request - ESC'n' system voltage
+    pc.printf   ("Responding ESC id=%d, volts=%.2f\r\n", (int)a.dbl[0], a.dbl[1]);
+}
+void    queryi  (struct parameters & a) {   //  Handle response from ESC resulting from prior TSC "n?i\r" sent request - ESC'n' motor pair currents
+    pc.printf   ("Responding ESC id=%d, I MotorA=%.2f, I MotorB=%.2f\r\n", (int)a.dbl[0], a.dbl[1], a.dbl[2]);
+}
+
 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[] = {
+*
+*   struct  kb_command const xx_list[]
+*
+*   Each line in list has 3 elements
+*       e.g. "ver\r" is message we may expect to be recieved here as a command or command response sent from somewhere else
+*       "waffle" is purely to inform you something about this message
+*       cmd is pointer to function, the what to do in response to the incoming message
+*           function type is void (*foo) (struct parameters &)
+*       This gives function access to parameters recieved with the message, e.g. "?i 7.45 8.23\r"
+*   User is at liberty to send using e.g. 'STM3_ESC_Interface::message' anything to any remote connected entity at any time.
+*   It is up to the user to ensure whatever is out there can make sense of it !
+*   The list of commands and responses the 'Brute_TS_Controller' is expected to recognise and act upon
+*   One such list for commands from pc terminal, another for comms with some number of STM3_Esc boards
+*/
 struct  kb_command const command_list[] = {
     {"ls", "Lists available commands", menucmd},
-    {"?", "Lists available commands, same as ls", menucmd},
-    {"ver", "report const_version_string", TSver_cmd},        //  Report TS controller version
+    {"?", "Lists available commands, same as ls", menucmd},     //  Send this list, a menu
+    {"ver", "report const_version_string", TSver_cmd},          //  Report TS controller version
     {"boards", "List STM3_ESC boards connected", boards_cmd},
-    {"kd", "kick the dog", kd_cmd},
+    {"kd", "kick the dog", kd_cmd},                             //  Broadcast Command to STM3_ESCs, resets and enables WatchDog timeout
+    {"?v", "Ask ESC for system voltage reading", queryv},           //  Makes no sense for pc to ask this of TS controller, just to test function
+    {"?i", "Ask ESC for pair of motor current readings", queryi},   //  Makes no sense for pc to ask this of TS controller, just to test function
     {"nu", "do nothing", null_cmd},
-};
+}   ;
 
 struct  kb_command const loco_command_list[] = {
-    {"ls", "Lists available commands", menucmd},
-    {"?", "Lists available commands, same as ls", menucmd},
     {"who", "Reads 'whon' response from STM3_ESC where 'n' is board num ascii from eeprom", who_cmd},
     {"ver", "report const_version_string", ver_req_cmd},    //  Request software version of one specific ESC board
     {"mph", "bogie mph reading", upmph_cmd},    //  22/06/2018
-    {"nu", "do nothing", null_cmd},
+    {"?v", "Ask ESC for system voltage reading", queryv},
+    {"?i", "Ask ESC for pair of motor current readings", queryi},
 }   ;
 
 
--- a/error_handler.cpp	Mon Jan 14 16:51:16 2019 +0000
+++ b/error_handler.cpp	Mon Mar 04 17:47:27 2019 +0000
@@ -69,10 +69,21 @@
 }
 
 extern  Serial  pc;
-void    error_handling_Jan_2019::report_any ()  {
+/*void    error_handling_Jan_2019::report_any ()  {
     for (int i = 0; i < NUMOF_REPORTABLE_TS_ERRORS; i++)  {
         if  (TS_fault[i])
             pc.printf   ("Error report, number %d, value %d, %s\r\n", i, TS_fault[i], FaultList[i]);
     }
 }
+*/
 
+void    error_handling_Jan_2019::report_any (bool   retain)  {
+    for (int i = 0; i < NUMOF_REPORTABLE_TS_ERRORS; i++)  {
+        if  (TS_fault[i])  {
+            pc.printf   ("Error report, number %d, value %d, %s\r\n", i, TS_fault[i], FaultList[i]);
+            if  (!retain)
+                TS_fault[i] = 0;
+        }
+    }
+}
+
--- a/main.cpp	Mon Jan 14 16:51:16 2019 +0000
+++ b/main.cpp	Mon Mar 04 17:47:27 2019 +0000
@@ -126,23 +126,30 @@
     int     bigImafptr;
     double  amps_longave,   //  internal use only
             amps_latest,    //  update() called @ 32Hz. Value stored here is average over most recent 3125us
-            amps_filtered;  //  Average of the BIGMAFSIZ most recent samples stored in latest
+            amps_filtered,  //  Average of the BIGMAFSIZ most recent samples stored in latest
+            amps_filtered2;  //  Average of the BIGMAFSIZ most recent samples stored in latest
 public:    
     ammeter_reading ()  {   //  constructor
         bigImafptr = 0;
-        amps_longave = amps_latest = amps_filtered = 0.0;
+        amps_longave = amps_latest = amps_filtered = amps_filtered2 = 0.0;
         for (int i = 0; i < BIGMAFSIZ; i++)
             bigImaf[i] = 0.0;
     }
     void    update  ()  ;   //  Read ammeter core, store most recent 32ms or so worth in amps_latest, 250ms average in amps_filtered
     double  latest  ()  ;
     double  filtered()  ;
+    double  filtered2()  ;
 }   Ammeter ;
 
 double  ammeter_reading::latest     ()  {
     return  amps_latest;
 }
 
+double  ammeter_reading::filtered2   ()  {
+//  could use filter without buffer, weights result more towards more frecent samples
+    return  amps_filtered2;
+}
+
 double  ammeter_reading::filtered   ()  {
     return  amps_filtered;
 }
@@ -156,6 +163,10 @@
     if  (bigImafptr >= BIGMAFSIZ)
         bigImafptr = 0;
     amps_filtered = amps_longave / BIGMAFSIZ;
+const   double  sampweight  = (double)(1) / (double)BIGMAFSIZ;
+const   double  shrinkby    = 1.0 - sampweight;
+    amps_filtered2 *= shrinkby;
+    amps_filtered2 += amps_latest * sampweight;
 }
 
 
@@ -247,9 +258,9 @@
     slider.direction = f_r_switch ? REV : FWD;      //  Only place in the code where direction gets set. Centre-Off power switch REV-OFF-FWD.
 
     My_STM3_ESC_boards.set_I_limit (0.0);
-    My_STM3_ESC_boards.set_V_limit (0.0);
-    My_STM3_ESC_boards.message  ("rb\r");
-    throttle    (0.0);      //  Set revs to idle. Start engine and warm up before powering up control
+    My_STM3_ESC_boards.set_V_limit (0.0);   //  zero power to motors
+    My_STM3_ESC_boards.message  ("rb\r");   //  regen brake mode
+    throttle    (0.0);                      //  Set revs to idle. Start engine and warm up before powering up control
     pc.printf   ("\r\n\n\nJon's Loco_TS_2018 Loco Controller ver %s starting, direction %s\r\n", const_version_string, slider.direction ? "Forward":"Reverse");
 
     uint8_t lcd_status = touch_screen.Init(lcd.GetXSize(), lcd.GetYSize());
@@ -311,25 +322,7 @@
             Speedo.set_value    (My_STM3_ESC_boards.mph);
 
             led_grn = !led_grn;
-/*
-Handbrake more sensibly implemented on STM3_ESC boards ?
-
-            if  (slider.state == PARK)   {
-                if  (My_STM3_ESC_boards.mph > LOCO_HANDBRAKE_ESCAPE_SPEED / 4.0)    {
-                    slider.handbrake_effort *= 1.1;
-                    if  (slider.handbrake_effort > 0.55)    slider.handbrake_effort = 0.55;
-                    set_run_mode    (PARK);
-                    pc.printf   ("Handbrake slipping, effort %.2f\r\n", slider.handbrake_effort);
-                }
-                if  (My_STM3_ESC_boards.mph < 0.02)    {
-                    slider.handbrake_effort *= 0.9;
-                    if  (slider.handbrake_effort < 0.05)    slider.handbrake_effort = 0.05;
-                    set_run_mode    (PARK);
-                    pc.printf   ("Handbrake not slipping, effort %.2f\r\n", slider.handbrake_effort);
-                }
-            }
-*/
-            My_STM3_ESC_boards.request_mph   (); //  issues "'n'rpm\r", takes care of cycling through available boards in sequence
+            My_STM3_ESC_boards.request_mph   (); //  issues "'n'mph\r", takes care of cycling through available boards in sequence
 //            switch  (qtr_sec)   {   //  Can do sequential stuff quarter second apart here
 //            }   //  End of switch qtr_sec
             qtr_sec++;
@@ -341,12 +334,13 @@
                     seconds = 0;
                     minutes++;
                     //  do once per minute stuff here
-                    Controller_Error.report_any ();
+                    Controller_Error.report_any (false);    //  Reset error having reported it once
                 }   //  fall back into once per second
                 if  (seconds & 1)
                     Speedo.LED  (0, LCD_COLOR_DARKGRAY);
                 else
                     Speedo.LED  (0, LCD_COLOR_RED);
+//                pc.printf   ("Filter test %.3f, %.3f\r\n", Ammeter.filtered(), Ammeter.filtered2());
                 My_STM3_ESC_boards.message  ("kd\r");       //  Kick the WatchDog timers in the Twin BLDC drive boards
                 recent_distance += (My_STM3_ESC_boards.mph * (111.76 * 4.0));    //  Convert mph to distance mm travelled in one second
                 uint32_t    new_metres = ((uint32_t)recent_distance) / 1000;