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
cli_BLS_nortos.cpp@13:ef7a06fa11de, 2019-09-29 (annotated)
- 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?
User | Revision | Line number | New 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 |