STM3 ESC dual brushless motor controller. 10-60v, motor power rating tiny to kW. Ganged or independent motor control As used in 'The Brute' locomotive - www.jons-workshop.com
Dependencies: mbed BufferedSerial Servo FastPWM
cli_BLS_nortos.cpp@12:d1d21a2941ef, 2019-03-04 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Mar 04 17:51:08 2019 +0000
- Revision:
- 12:d1d21a2941ef
- Parent:
- 11:bfb73f083009
STM3 ESC dual motor controller boards. Always 'Work In Progress', working snapshot March 2019
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 | 11:bfb73f083009 | 21 | #include "DualBLS.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 | 8:93203f473f6e | 29 | extern int WatchDog; |
JonFreeman | 8:93203f473f6e | 30 | extern bool WatchDogEnable; |
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 | 12:d1d21a2941ef | 205 | mode.wr(temps[1], MOTADIR); |
JonFreeman | 12:d1d21a2941ef | 206 | if (temps[2] > 0 && temps[2] < 5) |
JonFreeman | 12:d1d21a2941ef | 207 | mode.wr(temps[2], MOTBDIR); |
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 | 12:d1d21a2941ef | 268 | extern uint32_t last_temperature_count; |
JonFreeman | 12:d1d21a2941ef | 269 | /** |
JonFreeman | 12:d1d21a2941ef | 270 | * void temperature_cmd (struct parameters & a) { |
JonFreeman | 12:d1d21a2941ef | 271 | * Few boards have temperature sensor fitted. Non-preferred feature |
JonFreeman | 12:d1d21a2941ef | 272 | */ |
JonFreeman | 6:f289a49c1eae | 273 | void temperature_cmd (struct parameters & a) { |
JonFreeman | 6:f289a49c1eae | 274 | if (a.respond) { |
JonFreeman | 12:d1d21a2941ef | 275 | a.com->printf ("tem%c %d\r\n", mode.rd(BOARD_ID), (last_temperature_count / 16) - 50); |
JonFreeman | 6:f289a49c1eae | 276 | } |
JonFreeman | 6:f289a49c1eae | 277 | } |
JonFreeman | 6:f289a49c1eae | 278 | |
JonFreeman | 12:d1d21a2941ef | 279 | /** |
JonFreeman | 12:d1d21a2941ef | 280 | *void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors |
JonFreeman | 12:d1d21a2941ef | 281 | */ |
JonFreeman | 6:f289a49c1eae | 282 | void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors |
JonFreeman | 6:f289a49c1eae | 283 | { |
JonFreeman | 11:bfb73f083009 | 284 | if (a.respond) |
JonFreeman | 12:d1d21a2941ef | 285 | // 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 | 286 | 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 | 287 | } |
JonFreeman | 6:f289a49c1eae | 288 | |
JonFreeman | 12:d1d21a2941ef | 289 | /** |
JonFreeman | 12:d1d21a2941ef | 290 | *void mph_cmd (struct parameters & a) // to report miles per hour |
JonFreeman | 12:d1d21a2941ef | 291 | */ |
JonFreeman | 12:d1d21a2941ef | 292 | void mph_cmd (struct parameters & a) // to report miles per hour to 1 decimal place |
JonFreeman | 7:6deaeace9a3e | 293 | { |
JonFreeman | 11:bfb73f083009 | 294 | if (a.respond) |
JonFreeman | 12:d1d21a2941ef | 295 | // 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 | 296 | 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 | 297 | } |
JonFreeman | 12:d1d21a2941ef | 298 | |
JonFreeman | 12:d1d21a2941ef | 299 | /** |
JonFreeman | 12:d1d21a2941ef | 300 | *void sysV_report (struct parameters & a) // to report system voltage |
JonFreeman | 12:d1d21a2941ef | 301 | * Reports system link voltage to one decimal place |
JonFreeman | 12:d1d21a2941ef | 302 | */ |
JonFreeman | 12:d1d21a2941ef | 303 | void sysV_report (struct parameters & a) // |
JonFreeman | 12:d1d21a2941ef | 304 | { |
JonFreeman | 12:d1d21a2941ef | 305 | if (a.respond) |
JonFreeman | 12:d1d21a2941ef | 306 | a.com->printf ("?v%c %.1f\r%s", mode.rd(BOARD_ID), Read_BatteryVolts(), a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 7:6deaeace9a3e | 307 | } |
JonFreeman | 7:6deaeace9a3e | 308 | |
JonFreeman | 12:d1d21a2941ef | 309 | /** |
JonFreeman | 12:d1d21a2941ef | 310 | *void sysI_report (struct parameters & a) // to report motor currents |
JonFreeman | 12:d1d21a2941ef | 311 | * Reports doubles for each motor current amps to 2 decimal places |
JonFreeman | 12:d1d21a2941ef | 312 | */ |
JonFreeman | 12:d1d21a2941ef | 313 | void sysI_report (struct parameters & a) // |
JonFreeman | 12:d1d21a2941ef | 314 | { |
JonFreeman | 12:d1d21a2941ef | 315 | if (a.respond) // Calibration, refinement of 6000.0 (not miles out) first guess possible. |
JonFreeman | 12:d1d21a2941ef | 316 | // 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 | 317 | // 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 | 318 | 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 | 319 | } |
JonFreeman | 6:f289a49c1eae | 320 | |
JonFreeman | 12:d1d21a2941ef | 321 | |
JonFreeman | 12:d1d21a2941ef | 322 | /**void vi_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 323 | * |
JonFreeman | 12:d1d21a2941ef | 324 | * For setting motor voltage and current limits from pc terminal for test |
JonFreeman | 12:d1d21a2941ef | 325 | */ |
JonFreeman | 6:f289a49c1eae | 326 | void vi_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 327 | { |
JonFreeman | 6:f289a49c1eae | 328 | setVI (a.dbl[0] / 100.0, a.dbl[1] / 100.0); |
JonFreeman | 12:d1d21a2941ef | 329 | pc.printf ("setVI from %s\r\n", a.source == SOURCE_PC ? "PC" : "Touch Screen"); |
JonFreeman | 6:f289a49c1eae | 330 | } |
JonFreeman | 6:f289a49c1eae | 331 | |
JonFreeman | 12:d1d21a2941ef | 332 | /** |
JonFreeman | 12:d1d21a2941ef | 333 | *void v_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 334 | * Set motor voltage limit from either source without checking for addressed board |
JonFreeman | 12:d1d21a2941ef | 335 | */ |
JonFreeman | 6:f289a49c1eae | 336 | void v_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 337 | { |
JonFreeman | 12:d1d21a2941ef | 338 | MotorA.set_V_limit (a.dbl[0] / 100.0); |
JonFreeman | 12:d1d21a2941ef | 339 | MotorB.set_V_limit (a.dbl[0] / 100.0); |
JonFreeman | 6:f289a49c1eae | 340 | } |
JonFreeman | 6:f289a49c1eae | 341 | |
JonFreeman | 12:d1d21a2941ef | 342 | /** |
JonFreeman | 12:d1d21a2941ef | 343 | *void i_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 344 | * Set motor current limit from either source without checking for addressed board |
JonFreeman | 12:d1d21a2941ef | 345 | */ |
JonFreeman | 6:f289a49c1eae | 346 | void i_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 347 | { |
JonFreeman | 12:d1d21a2941ef | 348 | MotorA.set_I_limit (a.dbl[0] / 100.0); |
JonFreeman | 12:d1d21a2941ef | 349 | MotorB.set_I_limit (a.dbl[0] / 100.0); |
JonFreeman | 6:f289a49c1eae | 350 | } |
JonFreeman | 6:f289a49c1eae | 351 | |
JonFreeman | 12:d1d21a2941ef | 352 | /** |
JonFreeman | 12:d1d21a2941ef | 353 | *void kd_cmd (struct parameters & a) // kick and enable the watch dog |
JonFreeman | 12:d1d21a2941ef | 354 | * |
JonFreeman | 12:d1d21a2941ef | 355 | */ |
JonFreeman | 12:d1d21a2941ef | 356 | void kd_cmd (struct parameters & a) // kick the watchdog. Reached from TS or pc. |
JonFreeman | 6:f289a49c1eae | 357 | { |
JonFreeman | 12:d1d21a2941ef | 358 | WatchDog = WATCHDOG_RELOAD + (mode.rd(BOARD_ID) & 0x0f); // Reload watchdog timeout. Counted down @ 8Hz |
JonFreeman | 12:d1d21a2941ef | 359 | WatchDogEnable = true; // Receipt of this command sufficient to enable watchdog |
JonFreeman | 6:f289a49c1eae | 360 | } |
JonFreeman | 6:f289a49c1eae | 361 | |
JonFreeman | 12:d1d21a2941ef | 362 | /** |
JonFreeman | 12:d1d21a2941ef | 363 | *void who_cmd (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS |
JonFreeman | 12:d1d21a2941ef | 364 | * |
JonFreeman | 12:d1d21a2941ef | 365 | * When using STM3_ESC boards together with 'Brute Touch Screen Controller', controller needs to identify number and identity |
JonFreeman | 12:d1d21a2941ef | 366 | * of all connected STM3_ESC boards. To do this the Touch Screen issues '0who', '1who' ... '9who' allowing time between each |
JonFreeman | 12:d1d21a2941ef | 367 | * 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 | 368 | */ |
JonFreeman | 12:d1d21a2941ef | 369 | void who_cmd (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS |
JonFreeman | 6:f289a49c1eae | 370 | { |
JonFreeman | 12:d1d21a2941ef | 371 | if (a.source == SOURCE_PC || mode.rd(BOARD_ID) == a.target_unit) |
JonFreeman | 12:d1d21a2941ef | 372 | a.com->printf ("who%c\r%s", mode.rd(BOARD_ID), a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 6:f289a49c1eae | 373 | } |
JonFreeman | 6:f289a49c1eae | 374 | |
JonFreeman | 12:d1d21a2941ef | 375 | /** |
JonFreeman | 12:d1d21a2941ef | 376 | *void rcin_pccmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 377 | * |
JonFreeman | 12:d1d21a2941ef | 378 | * For test, reports to pc terminal info about radio control input channels |
JonFreeman | 12:d1d21a2941ef | 379 | */ |
JonFreeman | 10:e40d8724268a | 380 | void rcin_pccmd (struct parameters & a) |
JonFreeman | 10:e40d8724268a | 381 | { |
JonFreeman | 10:e40d8724268a | 382 | rcin_report (); |
JonFreeman | 10:e40d8724268a | 383 | } |
JonFreeman | 10:e40d8724268a | 384 | |
JonFreeman | 12:d1d21a2941ef | 385 | void scmd (struct parameters & a) // filter coefficient fiddler |
JonFreeman | 12:d1d21a2941ef | 386 | { |
JonFreeman | 12:d1d21a2941ef | 387 | switch ((int)a.dbl[0]) { |
JonFreeman | 12:d1d21a2941ef | 388 | case 1: |
JonFreeman | 12:d1d21a2941ef | 389 | MotorA.s[1] = MotorB.s[1] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 390 | break; |
JonFreeman | 12:d1d21a2941ef | 391 | case 2: |
JonFreeman | 12:d1d21a2941ef | 392 | MotorA.s[2] = MotorB.s[2] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 393 | break; |
JonFreeman | 12:d1d21a2941ef | 394 | case 3: |
JonFreeman | 12:d1d21a2941ef | 395 | MotorA.s[3] = MotorB.s[3] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 396 | break; |
JonFreeman | 12:d1d21a2941ef | 397 | case 4: |
JonFreeman | 12:d1d21a2941ef | 398 | MotorA.s[4] = MotorB.s[4] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 399 | break; |
JonFreeman | 12:d1d21a2941ef | 400 | case 5: |
JonFreeman | 12:d1d21a2941ef | 401 | MotorA.set_speed (a.dbl[1]); |
JonFreeman | 12:d1d21a2941ef | 402 | MotorB.set_speed (a.dbl[1]); |
JonFreeman | 12:d1d21a2941ef | 403 | break; |
JonFreeman | 12:d1d21a2941ef | 404 | default: |
JonFreeman | 12:d1d21a2941ef | 405 | pc.printf ("Wrong use of scmd %f\r\n", a.dbl[0]); |
JonFreeman | 12:d1d21a2941ef | 406 | } |
JonFreeman | 12:d1d21a2941ef | 407 | pc.printf ("Filter Coeffs 1 to 4\r\n"); |
JonFreeman | 12:d1d21a2941ef | 408 | pc.printf ("1 %.3f\tPscale 0.01-0.5\r\n", MotorA.s[1]); |
JonFreeman | 12:d1d21a2941ef | 409 | pc.printf ("2 %.3f\tP_gain 1.0-1000.0\r\n", MotorA.s[2]); |
JonFreeman | 12:d1d21a2941ef | 410 | pc.printf ("3 %.3f\tDscale 0.01-0.5\r\n", MotorA.s[3]); |
JonFreeman | 12:d1d21a2941ef | 411 | pc.printf ("4 %.3f\tD_gain 1.0-1000.0\r\n", MotorA.s[4]); |
JonFreeman | 12:d1d21a2941ef | 412 | pc.printf ("5 Set target_speed\r\n"); |
JonFreeman | 12:d1d21a2941ef | 413 | } |
JonFreeman | 12:d1d21a2941ef | 414 | |
JonFreeman | 12:d1d21a2941ef | 415 | struct kb_command { // Commands tabulated as list of these structures as seen below |
JonFreeman | 12:d1d21a2941ef | 416 | const char * cmd_word; // points to text e.g. "menu" |
JonFreeman | 12:d1d21a2941ef | 417 | const char * explan; // very brief explanation or clue as to purpose of function |
JonFreeman | 12:d1d21a2941ef | 418 | void (*f)(struct parameters &); // points to function |
JonFreeman | 12:d1d21a2941ef | 419 | } ; // Positioned in code here as knowledge needed by following menucmd |
JonFreeman | 12:d1d21a2941ef | 420 | |
JonFreeman | 12:d1d21a2941ef | 421 | /** |
JonFreeman | 12:d1d21a2941ef | 422 | * void menucmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 423 | * |
JonFreeman | 12:d1d21a2941ef | 424 | * List available terminal commands to pc terminal. No sense in touch screen using this |
JonFreeman | 12:d1d21a2941ef | 425 | */ |
JonFreeman | 12:d1d21a2941ef | 426 | void menucmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 427 | { |
JonFreeman | 12:d1d21a2941ef | 428 | if (a.respond) { |
JonFreeman | 12:d1d21a2941ef | 429 | 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 | 430 | for(int i = 0; i < a.numof_menu_items; i++) |
JonFreeman | 12:d1d21a2941ef | 431 | a.com->printf("[%s]\t\t%s\r\n", a.command_list[i].cmd_word, a.command_list[i].explan); |
JonFreeman | 12:d1d21a2941ef | 432 | a.com->printf("End of List of Commands\r\n"); |
JonFreeman | 12:d1d21a2941ef | 433 | } |
JonFreeman | 12:d1d21a2941ef | 434 | } |
JonFreeman | 12:d1d21a2941ef | 435 | |
JonFreeman | 12:d1d21a2941ef | 436 | /********************** END OF COMMAND LINE INTERPRETER COMMANDS *************************************/ |
JonFreeman | 6:f289a49c1eae | 437 | |
JonFreeman | 9:ac2412df01be | 438 | |
JonFreeman | 9:ac2412df01be | 439 | /** |
JonFreeman | 12:d1d21a2941ef | 440 | * struct kb_command const loco_command_list[] = { |
JonFreeman | 12:d1d21a2941ef | 441 | * List of commands accepted from external controller through opto isolated com port 19200, 8,n,1 |
JonFreeman | 9:ac2412df01be | 442 | */ |
JonFreeman | 12:d1d21a2941ef | 443 | struct kb_command const loco_command_list[] = { // For comms between STM3_ESC and 'Brute Touch Screen Controller' |
JonFreeman | 12:d1d21a2941ef | 444 | // ***** Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response ***** |
JonFreeman | 6:f289a49c1eae | 445 | {"fw", "forward", fw_cmd}, |
JonFreeman | 6:f289a49c1eae | 446 | {"re", "reverse", re_cmd}, |
JonFreeman | 6:f289a49c1eae | 447 | {"rb", "regen brake 0 to 99 %", rb_cmd}, |
JonFreeman | 6:f289a49c1eae | 448 | {"hb", "hand brake", hb_cmd}, |
JonFreeman | 6:f289a49c1eae | 449 | {"v", "set motors V percent RANGE 0 to 100", v_cmd}, |
JonFreeman | 6:f289a49c1eae | 450 | {"i", "set motors I percent RANGE 0 to 100", i_cmd}, |
JonFreeman | 6:f289a49c1eae | 451 | {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 452 | {"kd", "kick the dog, reloads WatchDog", kd_cmd}, |
JonFreeman | 12:d1d21a2941ef | 453 | // ***** Endof Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response ***** |
JonFreeman | 12:d1d21a2941ef | 454 | |
JonFreeman | 12:d1d21a2941ef | 455 | // ***** Following are rx'd requests for serial response from addressed STM3_ESC only |
JonFreeman | 12:d1d21a2941ef | 456 | {"?v", "Report system bus voltage", sysV_report}, |
JonFreeman | 12:d1d21a2941ef | 457 | {"?i", "Report motor both currents", sysI_report}, |
JonFreeman | 8:93203f473f6e | 458 | {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd}, |
JonFreeman | 6:f289a49c1eae | 459 | {"tem", "report temperature", temperature_cmd}, |
JonFreeman | 8:93203f473f6e | 460 | {"mph", "read loco speed miles per hour", mph_cmd}, |
JonFreeman | 12:d1d21a2941ef | 461 | // {"rvi", "read most recent values sent to pwms", rvi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 462 | // {"rdi", "read motor currents and power voltage", rdi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 463 | // ***** Endof |
JonFreeman | 12:d1d21a2941ef | 464 | } ; |
JonFreeman | 7:6deaeace9a3e | 465 | |
JonFreeman | 7:6deaeace9a3e | 466 | |
JonFreeman | 9:ac2412df01be | 467 | /** |
JonFreeman | 9:ac2412df01be | 468 | struct kb_command const loco_command_list[] = { |
JonFreeman | 9:ac2412df01be | 469 | List of commands accepted from external pc through non-opto isolated com port 9600, 8,n,1 |
JonFreeman | 9:ac2412df01be | 470 | */ |
JonFreeman | 7:6deaeace9a3e | 471 | struct kb_command const pc_command_list[] = { |
JonFreeman | 7:6deaeace9a3e | 472 | {"ls", "Lists available commands", menucmd}, |
JonFreeman | 7:6deaeace9a3e | 473 | {"?", "Lists available commands, same as ls", menucmd}, |
JonFreeman | 12:d1d21a2941ef | 474 | #ifdef USING_DC_MOTORS |
JonFreeman | 8:93203f473f6e | 475 | {"mtypes", "report types of motors found", mt_cmd}, |
JonFreeman | 12:d1d21a2941ef | 476 | #endif |
JonFreeman | 12:d1d21a2941ef | 477 | {"s","1-4, filter param", scmd}, |
JonFreeman | 8:93203f473f6e | 478 | {"pot", "read drivers control pot", pot_cmd}, |
JonFreeman | 7:6deaeace9a3e | 479 | {"fw", "forward", fw_cmd}, |
JonFreeman | 7:6deaeace9a3e | 480 | {"re", "reverse", re_cmd}, |
JonFreeman | 7:6deaeace9a3e | 481 | {"rb", "regen brake 0 to 99 %", rb_cmd}, |
JonFreeman | 7:6deaeace9a3e | 482 | {"hb", "hand brake", hb_cmd}, |
JonFreeman | 7:6deaeace9a3e | 483 | {"v", "set motors V percent RANGE 0 to 100", v_cmd}, |
JonFreeman | 7:6deaeace9a3e | 484 | {"i", "set motors I percent RANGE 0 to 100", i_cmd}, |
JonFreeman | 7:6deaeace9a3e | 485 | {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 486 | {"?v", "Report system bus voltage", sysV_report}, |
JonFreeman | 12:d1d21a2941ef | 487 | {"?i", "Report motor both currents", sysI_report}, |
JonFreeman | 8:93203f473f6e | 488 | {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd}, |
JonFreeman | 12:d1d21a2941ef | 489 | {"mode", "read or set params in eeprom", mode19_cmd}, // Big change Jan 2019 |
JonFreeman | 12:d1d21a2941ef | 490 | // {"erase", "set eeprom contents to all 0xff", erase_cmd}, |
JonFreeman | 12:d1d21a2941ef | 491 | {"tem", "report temperature", temperature_cmd}, // Reports -50 when sensor not fitted |
JonFreeman | 7:6deaeace9a3e | 492 | {"kd", "kick the dog, reloads WatchDog", kd_cmd}, |
JonFreeman | 12:d1d21a2941ef | 493 | {"ver", "Version", ver_cmd}, |
JonFreeman | 10:e40d8724268a | 494 | {"rcin", "Report Radio Control Input stuff", rcin_pccmd}, |
JonFreeman | 7:6deaeace9a3e | 495 | {"rpm", "read motor pair speeds", rpm_cmd}, |
JonFreeman | 7:6deaeace9a3e | 496 | {"mph", "read loco speed miles per hour", mph_cmd}, |
JonFreeman | 7:6deaeace9a3e | 497 | {"rvi", "read most recent values sent to pwms", rvi_cmd}, |
JonFreeman | 7:6deaeace9a3e | 498 | {"rdi", "read motor currents and power voltage", rdi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 499 | // {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd}, |
JonFreeman | 12:d1d21a2941ef | 500 | // {"gbb", "get bogie bytes from eeprom and report", gbb_cmd}, // OBSOLETE, replaced by 'gbb' |
JonFreeman | 7:6deaeace9a3e | 501 | {"nu", "do nothing", null_cmd}, |
JonFreeman | 12:d1d21a2941ef | 502 | } ; |
JonFreeman | 7:6deaeace9a3e | 503 | |
JonFreeman | 12:d1d21a2941ef | 504 | // cli_2019 (BufferedSerial * comport, kb_command const * list, int list_len, int source) { |
JonFreeman | 12:d1d21a2941ef | 505 | /** |
JonFreeman | 12:d1d21a2941ef | 506 | * cli_2019 pcc (&pc, pc_command_list, sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC) ; |
JonFreeman | 12:d1d21a2941ef | 507 | * cli_2019 tsc (&com2, loco_command_list, sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS) ; |
JonFreeman | 12:d1d21a2941ef | 508 | * |
JonFreeman | 12:d1d21a2941ef | 509 | * Instantiate two Command Line Interpreters, one for pc terminal and one for touch screen controller |
JonFreeman | 12:d1d21a2941ef | 510 | */ |
JonFreeman | 12:d1d21a2941ef | 511 | cli_2019 pcc (&pc, pc_command_list, sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC) ; |
JonFreeman | 12:d1d21a2941ef | 512 | cli_2019 tsc (&com2, loco_command_list, sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS) ; |
JonFreeman | 6:f289a49c1eae | 513 | |
JonFreeman | 6:f289a49c1eae | 514 | /* |
JonFreeman | 6:f289a49c1eae | 515 | New - March 2018 |
JonFreeman | 12:d1d21a2941ef | 516 | Using opto isolated serial port, paralleled up using same pair to multiple STM3_ESC boards running this code. |
JonFreeman | 6:f289a49c1eae | 517 | New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to. |
JonFreeman | 6:f289a49c1eae | 518 | Commands without prefix digit - broadcast to all units, all to obey but none to respond. |
JonFreeman | 6:f289a49c1eae | 519 | Only units recognising its address from prefix digit may respond. This avoids bus contention. |
JonFreeman | 6:f289a49c1eae | 520 | But for BROADCAST commands, '0' may respond on behalf of the group |
JonFreeman | 6:f289a49c1eae | 521 | */ |
JonFreeman | 12:d1d21a2941ef | 522 | |
JonFreeman | 12:d1d21a2941ef | 523 | /** |
JonFreeman | 12:d1d21a2941ef | 524 | * void cli_2019::test () { |
JonFreeman | 12:d1d21a2941ef | 525 | * |
JonFreeman | 12:d1d21a2941ef | 526 | * Daft check that class instantiation worked |
JonFreeman | 12:d1d21a2941ef | 527 | */ |
JonFreeman | 12:d1d21a2941ef | 528 | void cli_2019::test () { |
JonFreeman | 12:d1d21a2941ef | 529 | pc.printf ("At cli2019::test, source %d len %d,\r\n", a.source, a.numof_menu_items); |
JonFreeman | 12:d1d21a2941ef | 530 | } |
JonFreeman | 12:d1d21a2941ef | 531 | |
JonFreeman | 12:d1d21a2941ef | 532 | /** |
JonFreeman | 12:d1d21a2941ef | 533 | * void cli_2019::core () { |
JonFreeman | 12:d1d21a2941ef | 534 | * |
JonFreeman | 12:d1d21a2941ef | 535 | * Command Line Interpreter. |
JonFreeman | 12:d1d21a2941ef | 536 | * This to be called every few milli secs from main programme loop. |
JonFreeman | 12:d1d21a2941ef | 537 | * Reads any rx'd chars into command line buffer, returns when serial buffer empty. |
JonFreeman | 12:d1d21a2941ef | 538 | * 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 | 539 | * If matched command found, apt function is executed. |
JonFreeman | 12:d1d21a2941ef | 540 | * Parameters available to functions from 'parameters' struct. |
JonFreeman | 12:d1d21a2941ef | 541 | */ |
JonFreeman | 12:d1d21a2941ef | 542 | void cli_2019::core () { |
JonFreeman | 12:d1d21a2941ef | 543 | int ch, IAm = mode.rd(BOARD_ID); |
JonFreeman | 7:6deaeace9a3e | 544 | char * pEnd;//, * cmd_line_ptr; |
JonFreeman | 7:6deaeace9a3e | 545 | while (a.com->readable()) { |
JonFreeman | 7:6deaeace9a3e | 546 | ch = a.com->getc(); |
JonFreeman | 12:d1d21a2941ef | 547 | if (clindex > MAX_CMD_LEN) { // trap out stupidly long command lines |
JonFreeman | 12:d1d21a2941ef | 548 | ESC_Error.set (FAULT_COM_LINE_LEN, 1); // Set FAULT_EEPROM bit 0 if 24LC64 problem |
JonFreeman | 7:6deaeace9a3e | 549 | a.com->printf ("Error!! Stupidly long cmd line\r\n"); |
JonFreeman | 12:d1d21a2941ef | 550 | clindex = 0; |
JonFreeman | 7:6deaeace9a3e | 551 | } |
JonFreeman | 11:bfb73f083009 | 552 | if(ch != '\r') { // was this the 'Enter' key? |
JonFreeman | 11:bfb73f083009 | 553 | if (ch != '\n') // Ignore line feeds |
JonFreeman | 12:d1d21a2941ef | 554 | cmdline[clindex++] = ch; // added char to command being assembled |
JonFreeman | 11:bfb73f083009 | 555 | } |
JonFreeman | 7:6deaeace9a3e | 556 | else { // key was CR, may or may not be command to lookup |
JonFreeman | 7:6deaeace9a3e | 557 | a.target_unit = BROADCAST; // Set to BROADCAST default once found command line '\r' |
JonFreeman | 12:d1d21a2941ef | 558 | cmdline_ptr = cmdline; |
JonFreeman | 12:d1d21a2941ef | 559 | cmdline[clindex] = 0; // null terminate command string |
JonFreeman | 12:d1d21a2941ef | 560 | if(clindex) { // If have got some chars to lookup |
JonFreeman | 7:6deaeace9a3e | 561 | int i, wrdlen; |
JonFreeman | 12:d1d21a2941ef | 562 | if (isdigit(cmdline[0])) { // Look for command with prefix digit |
JonFreeman | 12:d1d21a2941ef | 563 | cmdline_ptr++; // point past identified digit prefix |
JonFreeman | 12:d1d21a2941ef | 564 | a.target_unit = cmdline[0]; // '0' to '9' |
JonFreeman | 7:6deaeace9a3e | 565 | //com->printf ("Got prefix %c\r\n", cmd_line[0]); |
JonFreeman | 7:6deaeace9a3e | 566 | } |
JonFreeman | 7:6deaeace9a3e | 567 | for (i = 0; i < a.numof_menu_items; i++) { // Look for input match in command list |
JonFreeman | 12:d1d21a2941ef | 568 | wrdlen = strlen(commandlist[i].cmd_word); |
JonFreeman | 12:d1d21a2941ef | 569 | if(strncmp(commandlist[i].cmd_word, cmdline_ptr, wrdlen) == 0 && !isalpha(cmdline_ptr[wrdlen])) { // If match found |
JonFreeman | 7:6deaeace9a3e | 570 | for (int k = 0; k < MAX_PARAMS; k++) { |
JonFreeman | 7:6deaeace9a3e | 571 | a.dbl[k] = 0.0; |
JonFreeman | 7:6deaeace9a3e | 572 | } |
JonFreeman | 7:6deaeace9a3e | 573 | a.position_in_list = i; |
JonFreeman | 7:6deaeace9a3e | 574 | a.numof_dbls = 0; |
JonFreeman | 12:d1d21a2941ef | 575 | pEnd = cmdline_ptr + wrdlen; |
JonFreeman | 7:6deaeace9a3e | 576 | while (*pEnd) { // Assemble all numerics as doubles |
JonFreeman | 7:6deaeace9a3e | 577 | a.dbl[a.numof_dbls++] = strtod (pEnd, &pEnd); |
JonFreeman | 7:6deaeace9a3e | 578 | while (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd) { |
JonFreeman | 7:6deaeace9a3e | 579 | pEnd++; |
JonFreeman | 7:6deaeace9a3e | 580 | } |
JonFreeman | 7:6deaeace9a3e | 581 | } |
JonFreeman | 7:6deaeace9a3e | 582 | a.respond = a.resp_always; |
JonFreeman | 7:6deaeace9a3e | 583 | if (((a.target_unit == BROADCAST) && (IAm == '0')) || (IAm == a.target_unit)) |
JonFreeman | 7:6deaeace9a3e | 584 | a.respond = true; // sorted 26/4/18 |
JonFreeman | 7:6deaeace9a3e | 585 | // All boards to obey BROADCAST command, only specific board to obey number prefixed command |
JonFreeman | 7:6deaeace9a3e | 586 | if ((a.target_unit == BROADCAST) || (IAm == a.target_unit)) |
JonFreeman | 12:d1d21a2941ef | 587 | commandlist[i].f(a); // execute command if addressed to this unit |
JonFreeman | 7:6deaeace9a3e | 588 | i = a.numof_menu_items + 1; // to exit for loop |
JonFreeman | 7:6deaeace9a3e | 589 | } // end of match found |
JonFreeman | 7:6deaeace9a3e | 590 | } // End of for numof_menu_items |
JonFreeman | 12:d1d21a2941ef | 591 | if(i == a.numof_menu_items) { |
JonFreeman | 12:d1d21a2941ef | 592 | // a.com->printf("No Match Found for CMD [%s]\r\n", cmdline); |
JonFreeman | 12:d1d21a2941ef | 593 | pc.printf("No Match Found for CMD [%s]\r\n", cmdline); |
JonFreeman | 12:d1d21a2941ef | 594 | ESC_Error.set (FAULT_COM_LINE_NOMATCH, 1); // Set FAULT_EEPROM bit 0 if 24LC64 problem |
JonFreeman | 12:d1d21a2941ef | 595 | } |
JonFreeman | 7:6deaeace9a3e | 596 | } // End of If have got some chars to lookup |
JonFreeman | 12:d1d21a2941ef | 597 | clindex = 0; |
JonFreeman | 12:d1d21a2941ef | 598 | } // End of else key was CR, may or may not be command to lookup |
JonFreeman | 12:d1d21a2941ef | 599 | } // End of while (com->readable()) |
JonFreeman | 12:d1d21a2941ef | 600 | } // end of command line interpreter core function |
JonFreeman | 6:f289a49c1eae | 601 | |
JonFreeman | 6:f289a49c1eae | 602 |