Dual Brushless Motor ESC, 10-62V, up to 50A per motor. Motors ganged or independent, multiple control input methods, cycle-by-cycle current limit, speed mode and torque mode control. Motors tiny to kW. Speed limit and other parameters easily set in firmware. As used in 'The Brushless Brutalist' locomotive - www.jons-workshop.com. See also Model Engineer magazine June-October 2019.

Dependencies:   mbed BufferedSerial Servo PCT2075 FastPWM

Update 17th August 2020 Radio control inputs completed

Committer:
JonFreeman
Date:
Sun Sep 29 16:34:37 2019 +0000
Revision:
13:ef7a06fa11de
Parent:
12:d1d21a2941ef
Child:
14:acaa1add097b
Stable code as at end of 2019 running season

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JonFreeman 12:d1d21a2941ef 1 /**
JonFreeman 12:d1d21a2941ef 2 * Code in this file : -
JonFreeman 12:d1d21a2941ef 3 *
JonFreeman 12:d1d21a2941ef 4 * STM3_ESC board uses two serial ports.
JonFreeman 12:d1d21a2941ef 5 * 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.
JonFreeman 12:d1d21a2941ef 6 *
JonFreeman 12:d1d21a2941ef 7 * com2 provides 19200 baud comms via opto-isolators to Touch Screen Controller (see "Brute_TS_Controller_2018_11"). Opto isolation allows
JonFreeman 12:d1d21a2941ef 8 * 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'.
JonFreeman 12:d1d21a2941ef 9 * This enables Touch Screen controller to address ESC boards individually e.g. for requesting speed, RPM etc
JonFreeman 12:d1d21a2941ef 10 * while also allowing broadcast of commands not requiring responses
JonFreeman 12:d1d21a2941ef 11 *
JonFreeman 12:d1d21a2941ef 12 * Code implements a Command Line Interpreter (see class cli_2019)
JonFreeman 12:d1d21a2941ef 13 * Two instantiations of class cli_2019 are used, 'pcc' for pc comms and 'tsc' for touch screen comms
JonFreeman 12:d1d21a2941ef 14 * These read incoming commands and execute code functions accordingly. These functions are all of type
JonFreeman 12:d1d21a2941ef 15 * void func (struct parameters &) ;
JonFreeman 12:d1d21a2941ef 16 * This allows any command line parameters to pass to 'func'
JonFreeman 12:d1d21a2941ef 17 */
JonFreeman 12:d1d21a2941ef 18 // Brushless_STM3_Ctrl_2018_11
JonFreeman 6:f289a49c1eae 19 #include "mbed.h"
JonFreeman 6:f289a49c1eae 20 #include "BufferedSerial.h"
JonFreeman 13:ef7a06fa11de 21 #include "STM3_ESC.h"
JonFreeman 11:bfb73f083009 22 #include "brushless_motor.h"
JonFreeman 6:f289a49c1eae 23
JonFreeman 6:f289a49c1eae 24 #include <cctype>
JonFreeman 6:f289a49c1eae 25 using namespace std;
JonFreeman 6:f289a49c1eae 26
JonFreeman 12:d1d21a2941ef 27 extern eeprom_settings mode ;
JonFreeman 12:d1d21a2941ef 28 extern error_handling_Jan_2019 ESC_Error ; // Provides array usable to store error codes.
JonFreeman 13:ef7a06fa11de 29 extern int WatchDog; // from main
JonFreeman 13:ef7a06fa11de 30 extern bool WatchDogEnable; // from main
JonFreeman 12:d1d21a2941ef 31 extern double rpm2mph ;
JonFreeman 11:bfb73f083009 32
JonFreeman 12:d1d21a2941ef 33 extern brushless_motor MotorA, MotorB; // Controlling two motors together or individually
JonFreeman 12:d1d21a2941ef 34 extern char const_version_string[] ;
JonFreeman 6:f289a49c1eae 35
JonFreeman 12:d1d21a2941ef 36 extern BufferedSerial com2, pc; // The two com ports used. There is also an unused com port, com3 setup @ 1200 baud
JonFreeman 12:d1d21a2941ef 37 extern void setVI (double v, double i) ; // Set motor voltage limit and current limit
JonFreeman 8:93203f473f6e 38 extern double Read_DriverPot ();
JonFreeman 11:bfb73f083009 39 extern double Read_BatteryVolts ();
JonFreeman 12:d1d21a2941ef 40 extern void mode_set_both_motors (int mode, double val) ; // called from cli to set fw, re, rb, hb
JonFreeman 12:d1d21a2941ef 41 extern void rcin_report () ;
JonFreeman 12:d1d21a2941ef 42
JonFreeman 12:d1d21a2941ef 43 // All void func (struct parameters &) ; functions addressed by command line interpreter are together below here
JonFreeman 12:d1d21a2941ef 44
JonFreeman 12:d1d21a2941ef 45 /**
JonFreeman 12:d1d21a2941ef 46 void ver_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 47 Responds YES, causes action NO
JonFreeman 12:d1d21a2941ef 48 PC or TS able to read software / firmware / hardware version string
JonFreeman 12:d1d21a2941ef 49 */
JonFreeman 12:d1d21a2941ef 50 void ver_cmd (struct parameters & a)
JonFreeman 8:93203f473f6e 51 {
JonFreeman 12:d1d21a2941ef 52 if (a.source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 53 pc.printf ("Version %s\r\n", const_version_string);
JonFreeman 12:d1d21a2941ef 54 else {
JonFreeman 12:d1d21a2941ef 55 if (a.source == SOURCE_TS)
JonFreeman 12:d1d21a2941ef 56 if (a.respond) // Only respond if this board addressed
JonFreeman 12:d1d21a2941ef 57 a.com->printf ("%s\r", const_version_string);
JonFreeman 12:d1d21a2941ef 58 else
JonFreeman 12:d1d21a2941ef 59 pc.printf ("Crap source %d in ver_cmd\r\n", a.source);
JonFreeman 12:d1d21a2941ef 60 }
JonFreeman 8:93203f473f6e 61 }
JonFreeman 6:f289a49c1eae 62
JonFreeman 12:d1d21a2941ef 63 /**
JonFreeman 12:d1d21a2941ef 64 void pot_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 65 Responds YES, causes action NO
JonFreeman 12:d1d21a2941ef 66 pc reads DriverPot. No sense in TS reading as STM3_ESC uses either/or TS, DriverPot
JonFreeman 12:d1d21a2941ef 67 */
JonFreeman 12:d1d21a2941ef 68 void pot_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 69 { if (a.source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 70 pc.printf ("Driver's pot %.3f\r\n", Read_DriverPot ());
JonFreeman 12:d1d21a2941ef 71 else
JonFreeman 12:d1d21a2941ef 72 pc.printf ("Wrong use of pot_cmd\r\n");
JonFreeman 12:d1d21a2941ef 73 }
JonFreeman 12:d1d21a2941ef 74
JonFreeman 12:d1d21a2941ef 75 /**
JonFreeman 12:d1d21a2941ef 76 * Do nothing command, but does report board ID code '0' to '9'
JonFreeman 12:d1d21a2941ef 77 */
JonFreeman 6:f289a49c1eae 78 void null_cmd (struct parameters & a)
JonFreeman 6:f289a49c1eae 79 {
JonFreeman 6:f289a49c1eae 80 if (a.respond)
JonFreeman 12:d1d21a2941ef 81 a.com->printf ("At null_cmd, board ID %c\r\n", mode.rd(BOARD_ID));
JonFreeman 8:93203f473f6e 82 }
JonFreeman 8:93203f473f6e 83
JonFreeman 12:d1d21a2941ef 84 #ifdef USING_DC_MOTORS
JonFreeman 12:d1d21a2941ef 85 /**
JonFreeman 12:d1d21a2941ef 86 void mt_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 87 PC Only
JonFreeman 12:d1d21a2941ef 88 Responds YES, causes action NO
JonFreeman 12:d1d21a2941ef 89 report_motor_types () // Reports 'Brushless' if Hall inputs read 1 to 6, 'DC' if no Hall sensors connected, therefore DC motor assumed
JonFreeman 12:d1d21a2941ef 90 */
JonFreeman 8:93203f473f6e 91 void mt_cmd (struct parameters & a)
JonFreeman 8:93203f473f6e 92 {
JonFreeman 12:d1d21a2941ef 93 if (a.source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 94 pc.printf ("Mot A is %s, Mot B is %s\r\n", MotorA.dc_motor ? "DC":"Brushless", MotorB.dc_motor ? "DC":"Brushless");
JonFreeman 12:d1d21a2941ef 95 else
JonFreeman 12:d1d21a2941ef 96 pc.printf ("Wrong use of mt_cmd\r\n");
JonFreeman 12:d1d21a2941ef 97 }
JonFreeman 12:d1d21a2941ef 98 #endif
JonFreeman 12:d1d21a2941ef 99
JonFreeman 12:d1d21a2941ef 100 /**
JonFreeman 12:d1d21a2941ef 101 * void rdi_cmd (struct parameters & a) // read motor currents (uint32_t) and BatteryVolts (double)
JonFreeman 12:d1d21a2941ef 102 */
JonFreeman 12:d1d21a2941ef 103 void rdi_cmd (struct parameters & a) // read motor currents (uint32_t) and BatteryVolts (double)
JonFreeman 12:d1d21a2941ef 104 { // Voltage reading true volts, currents only useful as relative values
JonFreeman 12:d1d21a2941ef 105 if (a.respond)
JonFreeman 12:d1d21a2941ef 106 // a.com->printf ("rdi%d %d %.1f\r%s", MotorA.I.ave, MotorB.I.ave, Read_BatteryVolts (), a.source == SOURCE_PC ? "\n" : "");
JonFreeman 12:d1d21a2941ef 107 a.com->printf ("rdi%.1f %.1f %.1f\r%s", MotorA.Idbl, MotorB.Idbl, Read_BatteryVolts (), a.source == SOURCE_PC ? "\n" : "");
JonFreeman 12:d1d21a2941ef 108 // Format good to be unpicked by cli in touch screen controller
JonFreeman 8:93203f473f6e 109 }
JonFreeman 8:93203f473f6e 110
JonFreeman 12:d1d21a2941ef 111 /**
JonFreeman 12:d1d21a2941ef 112 * void rvi_cmd (struct parameters & a) // read last normalised motor voltage and current values sent to pwms
JonFreeman 12:d1d21a2941ef 113 *
JonFreeman 12:d1d21a2941ef 114 */
JonFreeman 6:f289a49c1eae 115 void rvi_cmd (struct parameters & a) // read last normalised values sent to pwms
JonFreeman 6:f289a49c1eae 116 {
JonFreeman 11:bfb73f083009 117 if (a.respond)
JonFreeman 12:d1d21a2941ef 118 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" : "");
JonFreeman 6:f289a49c1eae 119 }
JonFreeman 6:f289a49c1eae 120
JonFreeman 12:d1d21a2941ef 121 /**
JonFreeman 12:d1d21a2941ef 122 * void fw_cmd (struct parameters & a) // Forward command
JonFreeman 12:d1d21a2941ef 123 * Broadcast to all STM3_ESC boards, required to ACT but NOT respond
JonFreeman 12:d1d21a2941ef 124 */
JonFreeman 12:d1d21a2941ef 125 void fw_cmd (struct parameters & a) // Forward command
JonFreeman 6:f289a49c1eae 126 {
JonFreeman 12:d1d21a2941ef 127 mode_set_both_motors (MOTOR_FORWARD, 0.0);
JonFreeman 12:d1d21a2941ef 128 if (a.source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 129 pc.printf ("fw\r\n"); // Show response to action if command from pc terminal
JonFreeman 6:f289a49c1eae 130 }
JonFreeman 6:f289a49c1eae 131
JonFreeman 12:d1d21a2941ef 132 /**
JonFreeman 12:d1d21a2941ef 133 * void re_cmd (struct parameters & a) // Reverse command
JonFreeman 12:d1d21a2941ef 134 * Broadcast to all STM3_ESC boards, required to ACT but NOT respond
JonFreeman 12:d1d21a2941ef 135 */
JonFreeman 12:d1d21a2941ef 136 void re_cmd (struct parameters & a) // Reverse command
JonFreeman 6:f289a49c1eae 137 {
JonFreeman 12:d1d21a2941ef 138 mode_set_both_motors (MOTOR_REVERSE, 0.0);
JonFreeman 12:d1d21a2941ef 139 if (a.source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 140 pc.printf ("re\r\n");
JonFreeman 8:93203f473f6e 141 }
JonFreeman 6:f289a49c1eae 142
JonFreeman 12:d1d21a2941ef 143 /**
JonFreeman 12:d1d21a2941ef 144 * void rb_cmd (struct parameters & a) // Regen brake command
JonFreeman 12:d1d21a2941ef 145 * Broadcast to all STM3_ESC boards, required to ACT but NOT respond
JonFreeman 12:d1d21a2941ef 146 */
JonFreeman 12:d1d21a2941ef 147 void rb_cmd (struct parameters & a) // Regen brake command
JonFreeman 6:f289a49c1eae 148 {
JonFreeman 12:d1d21a2941ef 149 mode_set_both_motors (MOTOR_REGENBRAKE, a.dbl[0] / 100.0);
JonFreeman 12:d1d21a2941ef 150 if (a.source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 151 pc.printf ("rb %.2f\r\n", a.dbl[0] / 100.0);
JonFreeman 6:f289a49c1eae 152 }
JonFreeman 6:f289a49c1eae 153
JonFreeman 12:d1d21a2941ef 154 /**
JonFreeman 12:d1d21a2941ef 155 * void hb_cmd (struct parameters & a) // Hand brake command
JonFreeman 12:d1d21a2941ef 156 * Broadcast to all STM3_ESC boards, required to ACT but NOT respond
JonFreeman 12:d1d21a2941ef 157 *
JonFreeman 12:d1d21a2941ef 158 * NOTE Jan 2019 Hand brake not implemented
JonFreeman 12:d1d21a2941ef 159 *
JonFreeman 6:f289a49c1eae 160 */
JonFreeman 12:d1d21a2941ef 161 void hb_cmd (struct parameters & a) // Hand brake command
JonFreeman 6:f289a49c1eae 162 {
JonFreeman 6:f289a49c1eae 163 if (a.respond) {
JonFreeman 7:6deaeace9a3e 164 a.com->printf ("numof params = %d\r\n", a.numof_dbls);
JonFreeman 7:6deaeace9a3e 165 a.com->printf ("Hand Brake : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
JonFreeman 6:f289a49c1eae 166 }
JonFreeman 12:d1d21a2941ef 167 mode_set_both_motors (MOTOR_HANDBRAKE, 0.0);
JonFreeman 6:f289a49c1eae 168 }
JonFreeman 6:f289a49c1eae 169
JonFreeman 12:d1d21a2941ef 170
JonFreeman 12:d1d21a2941ef 171 extern int numof_eeprom_options2 ;
JonFreeman 12:d1d21a2941ef 172 extern struct optpar const option_list2[] ;
JonFreeman 12:d1d21a2941ef 173 /**void mode_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents
JonFreeman 12:d1d21a2941ef 174 * mode_cmd called only from pc comms. No sense calling from Touch Screen Controller
JonFreeman 12:d1d21a2941ef 175 *
JonFreeman 12:d1d21a2941ef 176 * Called without parameters - Lists to pc terminal current settings
JonFreeman 12:d1d21a2941ef 177 *
JonFreeman 12:d1d21a2941ef 178 */
JonFreeman 12:d1d21a2941ef 179 void mode19_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents
JonFreeman 12:d1d21a2941ef 180 {
JonFreeman 12:d1d21a2941ef 181 char temps[36];
JonFreeman 12:d1d21a2941ef 182 int i;
JonFreeman 12:d1d21a2941ef 183 double topspeed; // New Jan 2019 - set max loco speed
JonFreeman 12:d1d21a2941ef 184 pc.printf ("\r\nmode - Set system data in EEPROM - Jan 2019\r\nSyntax 'mode' with no parameters lists current state.\r\n");
JonFreeman 12:d1d21a2941ef 185 if (a.numof_dbls) { // If more than 0 parameters supplied
JonFreeman 12:d1d21a2941ef 186 for (i = 0; i < a.numof_dbls; i++)
JonFreeman 12:d1d21a2941ef 187 temps[i] = (char)a.dbl[i]; // recast doubles to char
JonFreeman 12:d1d21a2941ef 188 while (i < 33)
JonFreeman 12:d1d21a2941ef 189 temps[i++] = 0;
JonFreeman 12:d1d21a2941ef 190 switch ((int)a.dbl[0]) {
JonFreeman 12:d1d21a2941ef 191 case 0: // MotorA_dir [0 or 1], MotorB_dir [0 or 1]
JonFreeman 12:d1d21a2941ef 192 if (temps[1] == 0 || temps[1] == 1)
JonFreeman 12:d1d21a2941ef 193 mode.wr(temps[1], MOTADIR);
JonFreeman 12:d1d21a2941ef 194 if (temps[2] == 0 || temps[2] == 1)
JonFreeman 12:d1d21a2941ef 195 mode.wr(temps[2], MOTBDIR);
JonFreeman 12:d1d21a2941ef 196 break;
JonFreeman 12:d1d21a2941ef 197 case 1: // MotorA_poles [4,6,8], MotorB_poles [4,6,8]
JonFreeman 12:d1d21a2941ef 198 if (temps[1] == 4 || temps[1] == 6 || temps[1] == 8)
JonFreeman 12:d1d21a2941ef 199 mode.wr(temps[1], MOTAPOLES);
JonFreeman 12:d1d21a2941ef 200 if (temps[2] == 4 || temps[2] == 6 || temps[2] == 8)
JonFreeman 12:d1d21a2941ef 201 mode.wr(temps[2], MOTBPOLES);
JonFreeman 12:d1d21a2941ef 202 break;
JonFreeman 12:d1d21a2941ef 203 case 2: // MotorA_ current sense resistors [1 to 4], MotorB_ current sense resistors [1 to 4]
JonFreeman 12:d1d21a2941ef 204 if (temps[1] > 0 && temps[1] < 5)
JonFreeman 13:ef7a06fa11de 205 mode.wr(temps[1], ISHUNTA); // Corrected since published
JonFreeman 12:d1d21a2941ef 206 if (temps[2] > 0 && temps[2] < 5)
JonFreeman 13:ef7a06fa11de 207 mode.wr(temps[2], ISHUNTB);
JonFreeman 12:d1d21a2941ef 208 break;
JonFreeman 12:d1d21a2941ef 209 case 3: // 2 Servo1 [0 or 1], Servo2 [0 or 1]
JonFreeman 12:d1d21a2941ef 210 if (temps[1] == 0 || temps[1] == 1)
JonFreeman 12:d1d21a2941ef 211 mode.wr(temps[1], SVO1);
JonFreeman 12:d1d21a2941ef 212 if (temps[2] == 0 || temps[2] == 1)
JonFreeman 12:d1d21a2941ef 213 mode.wr(temps[2], SVO2);
JonFreeman 12:d1d21a2941ef 214 break;
JonFreeman 12:d1d21a2941ef 215 case 4: // 3 RCIn1 [0 or 1], RCIn2 [0 or 1]
JonFreeman 12:d1d21a2941ef 216 if (temps[1] == 0 || temps[1] == 1)
JonFreeman 12:d1d21a2941ef 217 mode.wr(temps[1], RCIN1);
JonFreeman 12:d1d21a2941ef 218 if (temps[2] == 0 || temps[2] == 1)
JonFreeman 12:d1d21a2941ef 219 mode.wr(temps[2], RCIN2);
JonFreeman 12:d1d21a2941ef 220 break;
JonFreeman 12:d1d21a2941ef 221 case 5: // 4 Board ID '0' to '9'
JonFreeman 12:d1d21a2941ef 222 if (temps[1] <= 9) // pointless to compare unsigned integer with zero
JonFreeman 12:d1d21a2941ef 223 mode.wr('0' | temps[1], BOARD_ID);
JonFreeman 12:d1d21a2941ef 224 break;
JonFreeman 12:d1d21a2941ef 225 case 6: // TOP_SPEED
JonFreeman 12:d1d21a2941ef 226 topspeed = a.dbl[1];
JonFreeman 12:d1d21a2941ef 227 if (topspeed > 25.0) topspeed = 25.0;
JonFreeman 12:d1d21a2941ef 228 if (topspeed < 1.0) topspeed = 1.0;
JonFreeman 12:d1d21a2941ef 229 mode.wr((char)(topspeed * 10.0), TOP_SPEED);
JonFreeman 12:d1d21a2941ef 230 break;
JonFreeman 12:d1d21a2941ef 231 case 7: // 5 Wheel dia mm, Motor pinion teeth, Wheel gear teeth
JonFreeman 12:d1d21a2941ef 232 mode.wr(temps[1], WHEELDIA);
JonFreeman 12:d1d21a2941ef 233 mode.wr(temps[2], MOTPIN);
JonFreeman 12:d1d21a2941ef 234 mode.wr(temps[3], WHEELGEAR);
JonFreeman 12:d1d21a2941ef 235 break;
JonFreeman 12:d1d21a2941ef 236 case 8: // {2, 5, 2, "Command source 2= COM2 (Touch Screen), 3= Pot, 4= RC Input1, 5= RC Input2"},
JonFreeman 12:d1d21a2941ef 237 if (temps[1] > 1 && temps[1] < 6)
JonFreeman 12:d1d21a2941ef 238 mode.wr(temps[1], COMM_SRC);
JonFreeman 12:d1d21a2941ef 239 break;
JonFreeman 12:d1d21a2941ef 240 case 83: // set to defaults
JonFreeman 12:d1d21a2941ef 241 mode.set_defaults ();
JonFreeman 12:d1d21a2941ef 242 break;
JonFreeman 12:d1d21a2941ef 243 case 9: // 9 Save settings
JonFreeman 12:d1d21a2941ef 244 mode.save ();
JonFreeman 12:d1d21a2941ef 245 pc.printf ("Saving settings to EEPROM\r\n");
JonFreeman 12:d1d21a2941ef 246 break;
JonFreeman 12:d1d21a2941ef 247 default:
JonFreeman 12:d1d21a2941ef 248 break;
JonFreeman 12:d1d21a2941ef 249 } // endof switch
JonFreeman 12:d1d21a2941ef 250 } // endof // If more than 0 parameters supplied
JonFreeman 12:d1d21a2941ef 251 else {
JonFreeman 12:d1d21a2941ef 252 pc.printf ("No Changes\r\n");
JonFreeman 12:d1d21a2941ef 253 }
JonFreeman 12:d1d21a2941ef 254 pc.printf ("mode 0\tMotorA_dir [0 or 1]=%d, MotorB_dir [0 or 1]=%d\r\n", mode.rd(MOTADIR), mode.rd(MOTBDIR));
JonFreeman 12:d1d21a2941ef 255 pc.printf ("mode 1\tMotorA_poles [4,6,8]=%d, MotorB_poles [4,6,8]=%d\r\n", mode.rd(MOTAPOLES), mode.rd(MOTBPOLES));
JonFreeman 12:d1d21a2941ef 256 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));
JonFreeman 12:d1d21a2941ef 257 pc.printf ("mode 3\tServo1 [0 or 1]=%d, Servo2 [0 or 1]=%d\r\n", mode.rd(SVO1), mode.rd(SVO2));
JonFreeman 12:d1d21a2941ef 258 pc.printf ("mode 4\tRCIn1 [0 or 1]=%d, RCIn2 [0 or 1]=%d\r\n", mode.rd(RCIN1), mode.rd(RCIN2));
JonFreeman 12:d1d21a2941ef 259 pc.printf ("mode 5\tBoard ID ['0' to '9']='%c'\r\n", mode.rd(BOARD_ID));
JonFreeman 12:d1d21a2941ef 260 pc.printf ("mode 6\tTop Speed MPH [1.0 to 25.0]=%.1f\r\n", double(mode.rd(TOP_SPEED)) / 10.0);
JonFreeman 12:d1d21a2941ef 261 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));
JonFreeman 12:d1d21a2941ef 262 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));
JonFreeman 12:d1d21a2941ef 263 pc.printf ("mode 83\tSet to defaults\r\n");
JonFreeman 12:d1d21a2941ef 264 pc.printf ("mode 9\tSave settings\r\r\n");
JonFreeman 12:d1d21a2941ef 265
JonFreeman 12:d1d21a2941ef 266 }
JonFreeman 12:d1d21a2941ef 267
JonFreeman 13:ef7a06fa11de 268
JonFreeman 13:ef7a06fa11de 269 void ssl_cmd (struct parameters & a) { // set speed limit NEW and untested July 2019
JonFreeman 13:ef7a06fa11de 270 if (a.dbl[0] > 25.0) a.dbl[0] = 25.0;
JonFreeman 13:ef7a06fa11de 271 if (a.dbl[0] < 1.0) a.dbl[0] = 1.0;
JonFreeman 13:ef7a06fa11de 272 mode.wr((char)(a.dbl[0] * 10.0), TOP_SPEED);
JonFreeman 13:ef7a06fa11de 273 mode.save ();
JonFreeman 13:ef7a06fa11de 274 }
JonFreeman 13:ef7a06fa11de 275
JonFreeman 13:ef7a06fa11de 276 #ifdef TEMP_SENSOR_ENABLE
JonFreeman 13:ef7a06fa11de 277
JonFreeman 12:d1d21a2941ef 278 extern uint32_t last_temperature_count;
JonFreeman 12:d1d21a2941ef 279 /**
JonFreeman 12:d1d21a2941ef 280 * void temperature_cmd (struct parameters & a) {
JonFreeman 12:d1d21a2941ef 281 * Few boards have temperature sensor fitted. Non-preferred feature
JonFreeman 12:d1d21a2941ef 282 */
JonFreeman 6:f289a49c1eae 283 void temperature_cmd (struct parameters & a) {
JonFreeman 6:f289a49c1eae 284 if (a.respond) {
JonFreeman 12:d1d21a2941ef 285 a.com->printf ("tem%c %d\r\n", mode.rd(BOARD_ID), (last_temperature_count / 16) - 50);
JonFreeman 6:f289a49c1eae 286 }
JonFreeman 6:f289a49c1eae 287 }
JonFreeman 13:ef7a06fa11de 288 #endif
JonFreeman 6:f289a49c1eae 289
JonFreeman 12:d1d21a2941ef 290 /**
JonFreeman 12:d1d21a2941ef 291 *void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors
JonFreeman 12:d1d21a2941ef 292 */
JonFreeman 6:f289a49c1eae 293 void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors
JonFreeman 6:f289a49c1eae 294 {
JonFreeman 11:bfb73f083009 295 if (a.respond)
JonFreeman 12:d1d21a2941ef 296 // a.com->printf ("rpm%c %d %d\r%s", mode.rd(BOARD_ID), MotorA.RPM, MotorB.RPM, a.source == SOURCE_PC ? "\n" : "");
JonFreeman 12:d1d21a2941ef 297 a.com->printf ("rpm%c %.0f %.0f\r%s", mode.rd(BOARD_ID), MotorA.dRPM, MotorB.dRPM, a.source == SOURCE_PC ? "\n" : "");
JonFreeman 6:f289a49c1eae 298 }
JonFreeman 6:f289a49c1eae 299
JonFreeman 12:d1d21a2941ef 300 /**
JonFreeman 12:d1d21a2941ef 301 *void mph_cmd (struct parameters & a) // to report miles per hour
JonFreeman 12:d1d21a2941ef 302 */
JonFreeman 12:d1d21a2941ef 303 void mph_cmd (struct parameters & a) // to report miles per hour to 1 decimal place
JonFreeman 7:6deaeace9a3e 304 {
JonFreeman 11:bfb73f083009 305 if (a.respond)
JonFreeman 12:d1d21a2941ef 306 // 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" : "");
JonFreeman 12:d1d21a2941ef 307 a.com->printf ("mph%c %.1f\r%s", mode.rd(BOARD_ID), (double)(MotorA.dMPH + MotorB.dMPH) / 2.0, a.source == SOURCE_PC ? "\n" : "");
JonFreeman 12:d1d21a2941ef 308 }
JonFreeman 12:d1d21a2941ef 309
JonFreeman 12:d1d21a2941ef 310 /**
JonFreeman 12:d1d21a2941ef 311 *void sysV_report (struct parameters & a) // to report system voltage
JonFreeman 12:d1d21a2941ef 312 * Reports system link voltage to one decimal place
JonFreeman 12:d1d21a2941ef 313 */
JonFreeman 12:d1d21a2941ef 314 void sysV_report (struct parameters & a) //
JonFreeman 12:d1d21a2941ef 315 {
JonFreeman 12:d1d21a2941ef 316 if (a.respond)
JonFreeman 12:d1d21a2941ef 317 a.com->printf ("?v%c %.1f\r%s", mode.rd(BOARD_ID), Read_BatteryVolts(), a.source == SOURCE_PC ? "\n" : "");
JonFreeman 7:6deaeace9a3e 318 }
JonFreeman 7:6deaeace9a3e 319
JonFreeman 12:d1d21a2941ef 320 /**
JonFreeman 12:d1d21a2941ef 321 *void sysI_report (struct parameters & a) // to report motor currents
JonFreeman 12:d1d21a2941ef 322 * Reports doubles for each motor current amps to 2 decimal places
JonFreeman 12:d1d21a2941ef 323 */
JonFreeman 12:d1d21a2941ef 324 void sysI_report (struct parameters & a) //
JonFreeman 12:d1d21a2941ef 325 {
JonFreeman 12:d1d21a2941ef 326 if (a.respond) // Calibration, refinement of 6000.0 (not miles out) first guess possible.
JonFreeman 12:d1d21a2941ef 327 // 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" : "");
JonFreeman 12:d1d21a2941ef 328 // 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" : "");
JonFreeman 12:d1d21a2941ef 329 a.com->printf ("?i%c %.2f %.2f\r%s", mode.rd(BOARD_ID), MotorA.Idbl, MotorB.Idbl, a.source == SOURCE_PC ? "\n" : "");
JonFreeman 12:d1d21a2941ef 330 }
JonFreeman 6:f289a49c1eae 331
JonFreeman 12:d1d21a2941ef 332
JonFreeman 12:d1d21a2941ef 333 /**void vi_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 334 *
JonFreeman 12:d1d21a2941ef 335 * For setting motor voltage and current limits from pc terminal for test
JonFreeman 12:d1d21a2941ef 336 */
JonFreeman 6:f289a49c1eae 337 void vi_cmd (struct parameters & a)
JonFreeman 6:f289a49c1eae 338 {
JonFreeman 6:f289a49c1eae 339 setVI (a.dbl[0] / 100.0, a.dbl[1] / 100.0);
JonFreeman 12:d1d21a2941ef 340 pc.printf ("setVI from %s\r\n", a.source == SOURCE_PC ? "PC" : "Touch Screen");
JonFreeman 6:f289a49c1eae 341 }
JonFreeman 6:f289a49c1eae 342
JonFreeman 12:d1d21a2941ef 343 /**
JonFreeman 12:d1d21a2941ef 344 *void v_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 345 * Set motor voltage limit from either source without checking for addressed board
JonFreeman 12:d1d21a2941ef 346 */
JonFreeman 6:f289a49c1eae 347 void v_cmd (struct parameters & a)
JonFreeman 6:f289a49c1eae 348 {
JonFreeman 12:d1d21a2941ef 349 MotorA.set_V_limit (a.dbl[0] / 100.0);
JonFreeman 12:d1d21a2941ef 350 MotorB.set_V_limit (a.dbl[0] / 100.0);
JonFreeman 6:f289a49c1eae 351 }
JonFreeman 6:f289a49c1eae 352
JonFreeman 12:d1d21a2941ef 353 /**
JonFreeman 12:d1d21a2941ef 354 *void i_cmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 355 * Set motor current limit from either source without checking for addressed board
JonFreeman 12:d1d21a2941ef 356 */
JonFreeman 6:f289a49c1eae 357 void i_cmd (struct parameters & a)
JonFreeman 6:f289a49c1eae 358 {
JonFreeman 12:d1d21a2941ef 359 MotorA.set_I_limit (a.dbl[0] / 100.0);
JonFreeman 12:d1d21a2941ef 360 MotorB.set_I_limit (a.dbl[0] / 100.0);
JonFreeman 6:f289a49c1eae 361 }
JonFreeman 6:f289a49c1eae 362
JonFreeman 12:d1d21a2941ef 363 /**
JonFreeman 12:d1d21a2941ef 364 *void kd_cmd (struct parameters & a) // kick and enable the watch dog
JonFreeman 12:d1d21a2941ef 365 *
JonFreeman 13:ef7a06fa11de 366 * Brute_TS_Controller or other external controller to issue regular 'kd\r' to come here.
JonFreeman 13:ef7a06fa11de 367 * WatchDog disabled by default, enabled on first call to here
JonFreeman 13:ef7a06fa11de 368 * This is where WatchDog timer is reset and reloaded.
JonFreeman 13:ef7a06fa11de 369 * Timeout may be detected and handled in 8Hz loop in main programme loop
JonFreeman 12:d1d21a2941ef 370 */
JonFreeman 12:d1d21a2941ef 371 void kd_cmd (struct parameters & a) // kick the watchdog. Reached from TS or pc.
JonFreeman 6:f289a49c1eae 372 {
JonFreeman 12:d1d21a2941ef 373 WatchDog = WATCHDOG_RELOAD + (mode.rd(BOARD_ID) & 0x0f); // Reload watchdog timeout. Counted down @ 8Hz
JonFreeman 12:d1d21a2941ef 374 WatchDogEnable = true; // Receipt of this command sufficient to enable watchdog
JonFreeman 6:f289a49c1eae 375 }
JonFreeman 6:f289a49c1eae 376
JonFreeman 13:ef7a06fa11de 377 void wd_report (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS
JonFreeman 13:ef7a06fa11de 378 {
JonFreeman 13:ef7a06fa11de 379 pc.printf ("WatchDog %d\r\n", WatchDog);
JonFreeman 13:ef7a06fa11de 380 }
JonFreeman 12:d1d21a2941ef 381 /**
JonFreeman 12:d1d21a2941ef 382 *void who_cmd (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS
JonFreeman 12:d1d21a2941ef 383 *
JonFreeman 12:d1d21a2941ef 384 * When using STM3_ESC boards together with 'Brute Touch Screen Controller', controller needs to identify number and identity
JonFreeman 12:d1d21a2941ef 385 * of all connected STM3_ESC boards. To do this the Touch Screen issues '0who', '1who' ... '9who' allowing time between each
JonFreeman 12:d1d21a2941ef 386 * for an identified STM3_ESC to respond with 'who7' (if it was number 7) without causing contention of paralleled serial opto isolated bus
JonFreeman 12:d1d21a2941ef 387 */
JonFreeman 12:d1d21a2941ef 388 void who_cmd (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS
JonFreeman 6:f289a49c1eae 389 {
JonFreeman 12:d1d21a2941ef 390 if (a.source == SOURCE_PC || mode.rd(BOARD_ID) == a.target_unit)
JonFreeman 12:d1d21a2941ef 391 a.com->printf ("who%c\r%s", mode.rd(BOARD_ID), a.source == SOURCE_PC ? "\n" : "");
JonFreeman 6:f289a49c1eae 392 }
JonFreeman 6:f289a49c1eae 393
JonFreeman 12:d1d21a2941ef 394 /**
JonFreeman 12:d1d21a2941ef 395 *void rcin_pccmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 396 *
JonFreeman 12:d1d21a2941ef 397 * For test, reports to pc terminal info about radio control input channels
JonFreeman 12:d1d21a2941ef 398 */
JonFreeman 10:e40d8724268a 399 void rcin_pccmd (struct parameters & a)
JonFreeman 10:e40d8724268a 400 {
JonFreeman 10:e40d8724268a 401 rcin_report ();
JonFreeman 10:e40d8724268a 402 }
JonFreeman 10:e40d8724268a 403
JonFreeman 12:d1d21a2941ef 404 void scmd (struct parameters & a) // filter coefficient fiddler
JonFreeman 12:d1d21a2941ef 405 {
JonFreeman 12:d1d21a2941ef 406 switch ((int)a.dbl[0]) {
JonFreeman 12:d1d21a2941ef 407 case 1:
JonFreeman 13:ef7a06fa11de 408 MotorA.sdbl[1] = MotorB.sdbl[1] = a.dbl[1];
JonFreeman 12:d1d21a2941ef 409 break;
JonFreeman 12:d1d21a2941ef 410 case 2:
JonFreeman 13:ef7a06fa11de 411 MotorA.sdbl[2] = MotorB.sdbl[2] = a.dbl[1];
JonFreeman 12:d1d21a2941ef 412 break;
JonFreeman 12:d1d21a2941ef 413 case 3:
JonFreeman 13:ef7a06fa11de 414 MotorA.sdbl[3] = MotorB.sdbl[3] = a.dbl[1];
JonFreeman 12:d1d21a2941ef 415 break;
JonFreeman 12:d1d21a2941ef 416 case 4:
JonFreeman 13:ef7a06fa11de 417 MotorA.sdbl[4] = MotorB.sdbl[4] = a.dbl[1];
JonFreeman 12:d1d21a2941ef 418 break;
JonFreeman 12:d1d21a2941ef 419 case 5:
JonFreeman 12:d1d21a2941ef 420 MotorA.set_speed (a.dbl[1]);
JonFreeman 12:d1d21a2941ef 421 MotorB.set_speed (a.dbl[1]);
JonFreeman 12:d1d21a2941ef 422 break;
JonFreeman 12:d1d21a2941ef 423 default:
JonFreeman 12:d1d21a2941ef 424 pc.printf ("Wrong use of scmd %f\r\n", a.dbl[0]);
JonFreeman 12:d1d21a2941ef 425 }
JonFreeman 13:ef7a06fa11de 426 pc.printf ("Filter Coefficient Fiddler - used in brushless_motor::speed_monitor_and_control ()");
JonFreeman 12:d1d21a2941ef 427 pc.printf ("Filter Coeffs 1 to 4\r\n");
JonFreeman 13:ef7a06fa11de 428 pc.printf ("1 %.3f\tPscale 0.01-0.5\r\n", MotorA.sdbl[1]);
JonFreeman 13:ef7a06fa11de 429 pc.printf ("2 %.3f\tP_gain 1.0-1000.0\r\n", MotorA.sdbl[2]);
JonFreeman 13:ef7a06fa11de 430 pc.printf ("3 %.3f\tDscale 0.01-0.5\r\n", MotorA.sdbl[3]);
JonFreeman 13:ef7a06fa11de 431 pc.printf ("4 %.3f\tD_gain 1.0-1000.0\r\n", MotorA.sdbl[4]);
JonFreeman 12:d1d21a2941ef 432 pc.printf ("5 Set target_speed\r\n");
JonFreeman 12:d1d21a2941ef 433 }
JonFreeman 12:d1d21a2941ef 434
JonFreeman 12:d1d21a2941ef 435 struct kb_command { // Commands tabulated as list of these structures as seen below
JonFreeman 12:d1d21a2941ef 436 const char * cmd_word; // points to text e.g. "menu"
JonFreeman 12:d1d21a2941ef 437 const char * explan; // very brief explanation or clue as to purpose of function
JonFreeman 12:d1d21a2941ef 438 void (*f)(struct parameters &); // points to function
JonFreeman 12:d1d21a2941ef 439 } ; // Positioned in code here as knowledge needed by following menucmd
JonFreeman 12:d1d21a2941ef 440
JonFreeman 12:d1d21a2941ef 441 /**
JonFreeman 12:d1d21a2941ef 442 * void menucmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 443 *
JonFreeman 12:d1d21a2941ef 444 * List available terminal commands to pc terminal. No sense in touch screen using this
JonFreeman 12:d1d21a2941ef 445 */
JonFreeman 12:d1d21a2941ef 446 void menucmd (struct parameters & a)
JonFreeman 12:d1d21a2941ef 447 {
JonFreeman 12:d1d21a2941ef 448 if (a.respond) {
JonFreeman 12:d1d21a2941ef 449 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");
JonFreeman 12:d1d21a2941ef 450 for(int i = 0; i < a.numof_menu_items; i++)
JonFreeman 12:d1d21a2941ef 451 a.com->printf("[%s]\t\t%s\r\n", a.command_list[i].cmd_word, a.command_list[i].explan);
JonFreeman 12:d1d21a2941ef 452 a.com->printf("End of List of Commands\r\n");
JonFreeman 12:d1d21a2941ef 453 }
JonFreeman 12:d1d21a2941ef 454 }
JonFreeman 12:d1d21a2941ef 455
JonFreeman 12:d1d21a2941ef 456 /********************** END OF COMMAND LINE INTERPRETER COMMANDS *************************************/
JonFreeman 6:f289a49c1eae 457
JonFreeman 9:ac2412df01be 458
JonFreeman 9:ac2412df01be 459 /**
JonFreeman 12:d1d21a2941ef 460 * struct kb_command const loco_command_list[] = {
JonFreeman 12:d1d21a2941ef 461 * List of commands accepted from external controller through opto isolated com port 19200, 8,n,1
JonFreeman 9:ac2412df01be 462 */
JonFreeman 12:d1d21a2941ef 463 struct kb_command const loco_command_list[] = { // For comms between STM3_ESC and 'Brute Touch Screen Controller'
JonFreeman 12:d1d21a2941ef 464 // ***** Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response *****
JonFreeman 6:f289a49c1eae 465 {"fw", "forward", fw_cmd},
JonFreeman 6:f289a49c1eae 466 {"re", "reverse", re_cmd},
JonFreeman 6:f289a49c1eae 467 {"rb", "regen brake 0 to 99 %", rb_cmd},
JonFreeman 6:f289a49c1eae 468 {"hb", "hand brake", hb_cmd},
JonFreeman 6:f289a49c1eae 469 {"v", "set motors V percent RANGE 0 to 100", v_cmd},
JonFreeman 6:f289a49c1eae 470 {"i", "set motors I percent RANGE 0 to 100", i_cmd},
JonFreeman 6:f289a49c1eae 471 {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd},
JonFreeman 12:d1d21a2941ef 472 {"kd", "kick the dog, reloads WatchDog", kd_cmd},
JonFreeman 12:d1d21a2941ef 473 // ***** Endof Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response *****
JonFreeman 12:d1d21a2941ef 474
JonFreeman 12:d1d21a2941ef 475 // ***** Following are rx'd requests for serial response from addressed STM3_ESC only
JonFreeman 12:d1d21a2941ef 476 {"?v", "Report system bus voltage", sysV_report},
JonFreeman 12:d1d21a2941ef 477 {"?i", "Report motor both currents", sysI_report},
JonFreeman 8:93203f473f6e 478 {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd},
JonFreeman 13:ef7a06fa11de 479 #ifdef TEMP_SENSOR_ENABLE
JonFreeman 6:f289a49c1eae 480 {"tem", "report temperature", temperature_cmd},
JonFreeman 13:ef7a06fa11de 481 #endif
JonFreeman 8:93203f473f6e 482 {"mph", "read loco speed miles per hour", mph_cmd},
JonFreeman 13:ef7a06fa11de 483 {"ssl", "set speed limit e.g. 10.7", ssl_cmd}, // NEW July 2019
JonFreeman 12:d1d21a2941ef 484 // {"rvi", "read most recent values sent to pwms", rvi_cmd},
JonFreeman 12:d1d21a2941ef 485 // {"rdi", "read motor currents and power voltage", rdi_cmd},
JonFreeman 12:d1d21a2941ef 486 // ***** Endof
JonFreeman 12:d1d21a2941ef 487 } ;
JonFreeman 7:6deaeace9a3e 488
JonFreeman 7:6deaeace9a3e 489
JonFreeman 9:ac2412df01be 490 /**
JonFreeman 9:ac2412df01be 491 struct kb_command const loco_command_list[] = {
JonFreeman 9:ac2412df01be 492 List of commands accepted from external pc through non-opto isolated com port 9600, 8,n,1
JonFreeman 9:ac2412df01be 493 */
JonFreeman 7:6deaeace9a3e 494 struct kb_command const pc_command_list[] = {
JonFreeman 7:6deaeace9a3e 495 {"ls", "Lists available commands", menucmd},
JonFreeman 7:6deaeace9a3e 496 {"?", "Lists available commands, same as ls", menucmd},
JonFreeman 12:d1d21a2941ef 497 #ifdef USING_DC_MOTORS
JonFreeman 8:93203f473f6e 498 {"mtypes", "report types of motors found", mt_cmd},
JonFreeman 12:d1d21a2941ef 499 #endif
JonFreeman 13:ef7a06fa11de 500 {"s","1-4, RPM and speed filter param", scmd},
JonFreeman 8:93203f473f6e 501 {"pot", "read drivers control pot", pot_cmd},
JonFreeman 7:6deaeace9a3e 502 {"fw", "forward", fw_cmd},
JonFreeman 7:6deaeace9a3e 503 {"re", "reverse", re_cmd},
JonFreeman 7:6deaeace9a3e 504 {"rb", "regen brake 0 to 99 %", rb_cmd},
JonFreeman 7:6deaeace9a3e 505 {"hb", "hand brake", hb_cmd},
JonFreeman 7:6deaeace9a3e 506 {"v", "set motors V percent RANGE 0 to 100", v_cmd},
JonFreeman 7:6deaeace9a3e 507 {"i", "set motors I percent RANGE 0 to 100", i_cmd},
JonFreeman 7:6deaeace9a3e 508 {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd},
JonFreeman 12:d1d21a2941ef 509 {"?v", "Report system bus voltage", sysV_report},
JonFreeman 12:d1d21a2941ef 510 {"?i", "Report motor both currents", sysI_report},
JonFreeman 13:ef7a06fa11de 511 {"?w", "show WatchDog timer contents", wd_report},
JonFreeman 8:93203f473f6e 512 {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd},
JonFreeman 12:d1d21a2941ef 513 {"mode", "read or set params in eeprom", mode19_cmd}, // Big change Jan 2019
JonFreeman 13:ef7a06fa11de 514 {"ssl", "set speed limit e.g. 10.7", ssl_cmd}, // NEW July 2019 ONLY HERE FOR TEST, normal use is from Touch Screen only.
JonFreeman 12:d1d21a2941ef 515 // {"erase", "set eeprom contents to all 0xff", erase_cmd},
JonFreeman 13:ef7a06fa11de 516 #ifdef TEMP_SENSOR_ENABLE
JonFreeman 12:d1d21a2941ef 517 {"tem", "report temperature", temperature_cmd}, // Reports -50 when sensor not fitted
JonFreeman 13:ef7a06fa11de 518 #endif
JonFreeman 7:6deaeace9a3e 519 {"kd", "kick the dog, reloads WatchDog", kd_cmd},
JonFreeman 12:d1d21a2941ef 520 {"ver", "Version", ver_cmd},
JonFreeman 10:e40d8724268a 521 {"rcin", "Report Radio Control Input stuff", rcin_pccmd},
JonFreeman 7:6deaeace9a3e 522 {"rpm", "read motor pair speeds", rpm_cmd},
JonFreeman 7:6deaeace9a3e 523 {"mph", "read loco speed miles per hour", mph_cmd},
JonFreeman 7:6deaeace9a3e 524 {"rvi", "read most recent values sent to pwms", rvi_cmd},
JonFreeman 7:6deaeace9a3e 525 {"rdi", "read motor currents and power voltage", rdi_cmd},
JonFreeman 12:d1d21a2941ef 526 // {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd},
JonFreeman 12:d1d21a2941ef 527 // {"gbb", "get bogie bytes from eeprom and report", gbb_cmd}, // OBSOLETE, replaced by 'gbb'
JonFreeman 7:6deaeace9a3e 528 {"nu", "do nothing", null_cmd},
JonFreeman 12:d1d21a2941ef 529 } ;
JonFreeman 7:6deaeace9a3e 530
JonFreeman 12:d1d21a2941ef 531 // cli_2019 (BufferedSerial * comport, kb_command const * list, int list_len, int source) {
JonFreeman 12:d1d21a2941ef 532 /**
JonFreeman 12:d1d21a2941ef 533 * cli_2019 pcc (&pc, pc_command_list, sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC) ;
JonFreeman 12:d1d21a2941ef 534 * cli_2019 tsc (&com2, loco_command_list, sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS) ;
JonFreeman 12:d1d21a2941ef 535 *
JonFreeman 12:d1d21a2941ef 536 * Instantiate two Command Line Interpreters, one for pc terminal and one for touch screen controller
JonFreeman 12:d1d21a2941ef 537 */
JonFreeman 12:d1d21a2941ef 538 cli_2019 pcc (&pc, pc_command_list, sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC) ;
JonFreeman 12:d1d21a2941ef 539 cli_2019 tsc (&com2, loco_command_list, sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS) ;
JonFreeman 6:f289a49c1eae 540
JonFreeman 6:f289a49c1eae 541 /*
JonFreeman 6:f289a49c1eae 542 New - March 2018
JonFreeman 12:d1d21a2941ef 543 Using opto isolated serial port, paralleled up using same pair to multiple STM3_ESC boards running this code.
JonFreeman 6:f289a49c1eae 544 New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to.
JonFreeman 6:f289a49c1eae 545 Commands without prefix digit - broadcast to all units, all to obey but none to respond.
JonFreeman 6:f289a49c1eae 546 Only units recognising its address from prefix digit may respond. This avoids bus contention.
JonFreeman 6:f289a49c1eae 547 But for BROADCAST commands, '0' may respond on behalf of the group
JonFreeman 6:f289a49c1eae 548 */
JonFreeman 12:d1d21a2941ef 549
JonFreeman 12:d1d21a2941ef 550 /**
JonFreeman 12:d1d21a2941ef 551 * void cli_2019::test () {
JonFreeman 12:d1d21a2941ef 552 *
JonFreeman 12:d1d21a2941ef 553 * Daft check that class instantiation worked
JonFreeman 12:d1d21a2941ef 554 */
JonFreeman 12:d1d21a2941ef 555 void cli_2019::test () {
JonFreeman 12:d1d21a2941ef 556 pc.printf ("At cli2019::test, source %d len %d,\r\n", a.source, a.numof_menu_items);
JonFreeman 12:d1d21a2941ef 557 }
JonFreeman 12:d1d21a2941ef 558
JonFreeman 12:d1d21a2941ef 559 /**
JonFreeman 12:d1d21a2941ef 560 * void cli_2019::core () {
JonFreeman 12:d1d21a2941ef 561 *
JonFreeman 12:d1d21a2941ef 562 * Command Line Interpreter.
JonFreeman 12:d1d21a2941ef 563 * This to be called every few milli secs from main programme loop.
JonFreeman 12:d1d21a2941ef 564 * Reads any rx'd chars into command line buffer, returns when serial buffer empty.
JonFreeman 12:d1d21a2941ef 565 * If last char rx'd war '\r' end of text delimiter, apt command_list is searched for a matched command in command line
JonFreeman 12:d1d21a2941ef 566 * If matched command found, apt function is executed.
JonFreeman 12:d1d21a2941ef 567 * Parameters available to functions from 'parameters' struct.
JonFreeman 12:d1d21a2941ef 568 */
JonFreeman 12:d1d21a2941ef 569 void cli_2019::core () {
JonFreeman 12:d1d21a2941ef 570 int ch, IAm = mode.rd(BOARD_ID);
JonFreeman 7:6deaeace9a3e 571 char * pEnd;//, * cmd_line_ptr;
JonFreeman 7:6deaeace9a3e 572 while (a.com->readable()) {
JonFreeman 7:6deaeace9a3e 573 ch = a.com->getc();
JonFreeman 12:d1d21a2941ef 574 if (clindex > MAX_CMD_LEN) { // trap out stupidly long command lines
JonFreeman 12:d1d21a2941ef 575 ESC_Error.set (FAULT_COM_LINE_LEN, 1); // Set FAULT_EEPROM bit 0 if 24LC64 problem
JonFreeman 7:6deaeace9a3e 576 a.com->printf ("Error!! Stupidly long cmd line\r\n");
JonFreeman 12:d1d21a2941ef 577 clindex = 0;
JonFreeman 7:6deaeace9a3e 578 }
JonFreeman 11:bfb73f083009 579 if(ch != '\r') { // was this the 'Enter' key?
JonFreeman 11:bfb73f083009 580 if (ch != '\n') // Ignore line feeds
JonFreeman 12:d1d21a2941ef 581 cmdline[clindex++] = ch; // added char to command being assembled
JonFreeman 11:bfb73f083009 582 }
JonFreeman 7:6deaeace9a3e 583 else { // key was CR, may or may not be command to lookup
JonFreeman 7:6deaeace9a3e 584 a.target_unit = BROADCAST; // Set to BROADCAST default once found command line '\r'
JonFreeman 12:d1d21a2941ef 585 cmdline_ptr = cmdline;
JonFreeman 12:d1d21a2941ef 586 cmdline[clindex] = 0; // null terminate command string
JonFreeman 12:d1d21a2941ef 587 if(clindex) { // If have got some chars to lookup
JonFreeman 7:6deaeace9a3e 588 int i, wrdlen;
JonFreeman 12:d1d21a2941ef 589 if (isdigit(cmdline[0])) { // Look for command with prefix digit
JonFreeman 12:d1d21a2941ef 590 cmdline_ptr++; // point past identified digit prefix
JonFreeman 12:d1d21a2941ef 591 a.target_unit = cmdline[0]; // '0' to '9'
JonFreeman 7:6deaeace9a3e 592 //com->printf ("Got prefix %c\r\n", cmd_line[0]);
JonFreeman 7:6deaeace9a3e 593 }
JonFreeman 7:6deaeace9a3e 594 for (i = 0; i < a.numof_menu_items; i++) { // Look for input match in command list
JonFreeman 12:d1d21a2941ef 595 wrdlen = strlen(commandlist[i].cmd_word);
JonFreeman 12:d1d21a2941ef 596 if(strncmp(commandlist[i].cmd_word, cmdline_ptr, wrdlen) == 0 && !isalpha(cmdline_ptr[wrdlen])) { // If match found
JonFreeman 7:6deaeace9a3e 597 for (int k = 0; k < MAX_PARAMS; k++) {
JonFreeman 7:6deaeace9a3e 598 a.dbl[k] = 0.0;
JonFreeman 7:6deaeace9a3e 599 }
JonFreeman 7:6deaeace9a3e 600 a.position_in_list = i;
JonFreeman 7:6deaeace9a3e 601 a.numof_dbls = 0;
JonFreeman 12:d1d21a2941ef 602 pEnd = cmdline_ptr + wrdlen;
JonFreeman 7:6deaeace9a3e 603 while (*pEnd) { // Assemble all numerics as doubles
JonFreeman 7:6deaeace9a3e 604 a.dbl[a.numof_dbls++] = strtod (pEnd, &pEnd);
JonFreeman 7:6deaeace9a3e 605 while (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd) {
JonFreeman 7:6deaeace9a3e 606 pEnd++;
JonFreeman 7:6deaeace9a3e 607 }
JonFreeman 7:6deaeace9a3e 608 }
JonFreeman 7:6deaeace9a3e 609 a.respond = a.resp_always;
JonFreeman 7:6deaeace9a3e 610 if (((a.target_unit == BROADCAST) && (IAm == '0')) || (IAm == a.target_unit))
JonFreeman 7:6deaeace9a3e 611 a.respond = true; // sorted 26/4/18
JonFreeman 7:6deaeace9a3e 612 // All boards to obey BROADCAST command, only specific board to obey number prefixed command
JonFreeman 7:6deaeace9a3e 613 if ((a.target_unit == BROADCAST) || (IAm == a.target_unit))
JonFreeman 12:d1d21a2941ef 614 commandlist[i].f(a); // execute command if addressed to this unit
JonFreeman 7:6deaeace9a3e 615 i = a.numof_menu_items + 1; // to exit for loop
JonFreeman 7:6deaeace9a3e 616 } // end of match found
JonFreeman 7:6deaeace9a3e 617 } // End of for numof_menu_items
JonFreeman 12:d1d21a2941ef 618 if(i == a.numof_menu_items) {
JonFreeman 12:d1d21a2941ef 619 // a.com->printf("No Match Found for CMD [%s]\r\n", cmdline);
JonFreeman 12:d1d21a2941ef 620 pc.printf("No Match Found for CMD [%s]\r\n", cmdline);
JonFreeman 12:d1d21a2941ef 621 ESC_Error.set (FAULT_COM_LINE_NOMATCH, 1); // Set FAULT_EEPROM bit 0 if 24LC64 problem
JonFreeman 12:d1d21a2941ef 622 }
JonFreeman 7:6deaeace9a3e 623 } // End of If have got some chars to lookup
JonFreeman 12:d1d21a2941ef 624 clindex = 0;
JonFreeman 12:d1d21a2941ef 625 } // End of else key was CR, may or may not be command to lookup
JonFreeman 12:d1d21a2941ef 626 } // End of while (com->readable())
JonFreeman 12:d1d21a2941ef 627 } // end of command line interpreter core function
JonFreeman 6:f289a49c1eae 628
JonFreeman 6:f289a49c1eae 629