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@17:cc9b854295d6, 2020-08-16 (annotated)
- Committer:
- JonFreeman
- Date:
- Sun Aug 16 14:13:19 2020 +0000
- Revision:
- 17:cc9b854295d6
- Parent:
- 16:d1e4b9ad3b8b
August 2020. Checked Radio Control input ops.
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 | 16:d1e4b9ad3b8b | 27 | extern eeprom_settings user_settings ; |
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 | 17:cc9b854295d6 | 31 | //extern bool read_temperature (float & t) ; // from main March 2020 |
JonFreeman | 11:bfb73f083009 | 32 | |
JonFreeman | 12:d1d21a2941ef | 33 | extern brushless_motor MotorA, MotorB; // Controlling two motors together or individually |
JonFreeman | 16:d1e4b9ad3b8b | 34 | extern const char * get_version () ; // Need this as extern const char can not be made to work. This returns & 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 | 16:d1e4b9ad3b8b | 37 | extern void setVI_both (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 | 16:d1e4b9ad3b8b | 40 | extern void mode_set_motors_both (int mode) ; // called from cli to set fw, re, rb, hb |
JonFreeman | 12:d1d21a2941ef | 41 | |
JonFreeman | 12:d1d21a2941ef | 42 | // All void func (struct parameters &) ; functions addressed by command line interpreter are together below here |
JonFreeman | 12:d1d21a2941ef | 43 | |
JonFreeman | 12:d1d21a2941ef | 44 | /** |
JonFreeman | 12:d1d21a2941ef | 45 | void ver_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 46 | Responds YES, causes action NO |
JonFreeman | 12:d1d21a2941ef | 47 | PC or TS able to read software / firmware / hardware version string |
JonFreeman | 12:d1d21a2941ef | 48 | */ |
JonFreeman | 12:d1d21a2941ef | 49 | void ver_cmd (struct parameters & a) |
JonFreeman | 8:93203f473f6e | 50 | { |
JonFreeman | 16:d1e4b9ad3b8b | 51 | if (a.source == SOURCE_PC) { |
JonFreeman | 16:d1e4b9ad3b8b | 52 | pc.printf ("Version [%s]\r\n", get_version()); |
JonFreeman | 16:d1e4b9ad3b8b | 53 | } |
JonFreeman | 12:d1d21a2941ef | 54 | else { |
JonFreeman | 12:d1d21a2941ef | 55 | if (a.source == SOURCE_TS) |
JonFreeman | 16:d1e4b9ad3b8b | 56 | if (a.respond) { // Only respond if this board addressed |
JonFreeman | 16:d1e4b9ad3b8b | 57 | a.com->printf ("%s\r", get_version()); |
JonFreeman | 16:d1e4b9ad3b8b | 58 | } |
JonFreeman | 12:d1d21a2941ef | 59 | else |
JonFreeman | 12:d1d21a2941ef | 60 | pc.printf ("Crap source %d in ver_cmd\r\n", a.source); |
JonFreeman | 12:d1d21a2941ef | 61 | } |
JonFreeman | 8:93203f473f6e | 62 | } |
JonFreeman | 6:f289a49c1eae | 63 | |
JonFreeman | 12:d1d21a2941ef | 64 | /** |
JonFreeman | 12:d1d21a2941ef | 65 | void pot_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 66 | Responds YES, causes action NO |
JonFreeman | 12:d1d21a2941ef | 67 | pc reads DriverPot. No sense in TS reading as STM3_ESC uses either/or TS, DriverPot |
JonFreeman | 12:d1d21a2941ef | 68 | */ |
JonFreeman | 12:d1d21a2941ef | 69 | void pot_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 70 | { if (a.source == SOURCE_PC) |
JonFreeman | 12:d1d21a2941ef | 71 | pc.printf ("Driver's pot %.3f\r\n", Read_DriverPot ()); |
JonFreeman | 12:d1d21a2941ef | 72 | else |
JonFreeman | 12:d1d21a2941ef | 73 | pc.printf ("Wrong use of pot_cmd\r\n"); |
JonFreeman | 12:d1d21a2941ef | 74 | } |
JonFreeman | 12:d1d21a2941ef | 75 | |
JonFreeman | 12:d1d21a2941ef | 76 | /** |
JonFreeman | 12:d1d21a2941ef | 77 | * Do nothing command, but does report board ID code '0' to '9' |
JonFreeman | 12:d1d21a2941ef | 78 | */ |
JonFreeman | 6:f289a49c1eae | 79 | void null_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 80 | { |
JonFreeman | 6:f289a49c1eae | 81 | if (a.respond) |
JonFreeman | 16:d1e4b9ad3b8b | 82 | a.com->printf ("Board ID %c\r\n", user_settings.rd(BOARD_ID)); |
JonFreeman | 8:93203f473f6e | 83 | } |
JonFreeman | 8:93203f473f6e | 84 | |
JonFreeman | 12:d1d21a2941ef | 85 | |
JonFreeman | 12:d1d21a2941ef | 86 | /** |
JonFreeman | 12:d1d21a2941ef | 87 | * void rdi_cmd (struct parameters & a) // read motor currents (uint32_t) and BatteryVolts (double) |
JonFreeman | 16:d1e4b9ad3b8b | 88 | |
JonFreeman | 12:d1d21a2941ef | 89 | void rdi_cmd (struct parameters & a) // read motor currents (uint32_t) and BatteryVolts (double) |
JonFreeman | 12:d1d21a2941ef | 90 | { // Voltage reading true volts, currents only useful as relative values |
JonFreeman | 12:d1d21a2941ef | 91 | if (a.respond) |
JonFreeman | 12:d1d21a2941ef | 92 | // 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 | 93 | a.com->printf ("rdi%.1f %.1f %.1f\r%s", MotorA.Idbl, MotorB.Idbl, Read_BatteryVolts (), a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 12:d1d21a2941ef | 94 | // Format good to be unpicked by cli in touch screen controller |
JonFreeman | 8:93203f473f6e | 95 | } |
JonFreeman | 16:d1e4b9ad3b8b | 96 | */ |
JonFreeman | 12:d1d21a2941ef | 97 | /** |
JonFreeman | 12:d1d21a2941ef | 98 | * void rvi_cmd (struct parameters & a) // read last normalised motor voltage and current values sent to pwms |
JonFreeman | 12:d1d21a2941ef | 99 | * |
JonFreeman | 12:d1d21a2941ef | 100 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 101 | //void rvi_cmd (struct parameters & a) // read last normalised values sent to pwms |
JonFreeman | 16:d1e4b9ad3b8b | 102 | //{ |
JonFreeman | 16:d1e4b9ad3b8b | 103 | // if (a.respond) |
JonFreeman | 16:d1e4b9ad3b8b | 104 | // 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 | 16:d1e4b9ad3b8b | 105 | //} |
JonFreeman | 6:f289a49c1eae | 106 | |
JonFreeman | 12:d1d21a2941ef | 107 | /** |
JonFreeman | 12:d1d21a2941ef | 108 | * void fw_cmd (struct parameters & a) // Forward command |
JonFreeman | 12:d1d21a2941ef | 109 | * Broadcast to all STM3_ESC boards, required to ACT but NOT respond |
JonFreeman | 12:d1d21a2941ef | 110 | */ |
JonFreeman | 12:d1d21a2941ef | 111 | void fw_cmd (struct parameters & a) // Forward command |
JonFreeman | 6:f289a49c1eae | 112 | { |
JonFreeman | 16:d1e4b9ad3b8b | 113 | // MotorA.set_mode (MOTOR_FORWARD); |
JonFreeman | 16:d1e4b9ad3b8b | 114 | // MotorB.set_mode (MOTOR_FORWARD); |
JonFreeman | 16:d1e4b9ad3b8b | 115 | mode_set_motors_both (MOTOR_FORWARD); |
JonFreeman | 12:d1d21a2941ef | 116 | if (a.source == SOURCE_PC) |
JonFreeman | 12:d1d21a2941ef | 117 | pc.printf ("fw\r\n"); // Show response to action if command from pc terminal |
JonFreeman | 6:f289a49c1eae | 118 | } |
JonFreeman | 6:f289a49c1eae | 119 | |
JonFreeman | 12:d1d21a2941ef | 120 | /** |
JonFreeman | 12:d1d21a2941ef | 121 | * void re_cmd (struct parameters & a) // Reverse command |
JonFreeman | 12:d1d21a2941ef | 122 | * Broadcast to all STM3_ESC boards, required to ACT but NOT respond |
JonFreeman | 12:d1d21a2941ef | 123 | */ |
JonFreeman | 12:d1d21a2941ef | 124 | void re_cmd (struct parameters & a) // Reverse command |
JonFreeman | 6:f289a49c1eae | 125 | { |
JonFreeman | 16:d1e4b9ad3b8b | 126 | mode_set_motors_both (MOTOR_REVERSE); |
JonFreeman | 12:d1d21a2941ef | 127 | if (a.source == SOURCE_PC) |
JonFreeman | 12:d1d21a2941ef | 128 | pc.printf ("re\r\n"); |
JonFreeman | 8:93203f473f6e | 129 | } |
JonFreeman | 6:f289a49c1eae | 130 | |
JonFreeman | 12:d1d21a2941ef | 131 | /** |
JonFreeman | 12:d1d21a2941ef | 132 | * void rb_cmd (struct parameters & a) // Regen brake command |
JonFreeman | 12:d1d21a2941ef | 133 | * Broadcast to all STM3_ESC boards, required to ACT but NOT respond |
JonFreeman | 12:d1d21a2941ef | 134 | */ |
JonFreeman | 12:d1d21a2941ef | 135 | void rb_cmd (struct parameters & a) // Regen brake command |
JonFreeman | 6:f289a49c1eae | 136 | { |
JonFreeman | 16:d1e4b9ad3b8b | 137 | double tmp = a.dbl[0] / 100.0; |
JonFreeman | 16:d1e4b9ad3b8b | 138 | MotorA.brake (tmp); |
JonFreeman | 16:d1e4b9ad3b8b | 139 | MotorB.brake (tmp); // Corrected May 2020 - previously MotorA twice |
JonFreeman | 12:d1d21a2941ef | 140 | if (a.source == SOURCE_PC) |
JonFreeman | 16:d1e4b9ad3b8b | 141 | pc.printf ("rb %.2f\r\n", tmp); |
JonFreeman | 6:f289a49c1eae | 142 | } |
JonFreeman | 6:f289a49c1eae | 143 | |
JonFreeman | 12:d1d21a2941ef | 144 | /** |
JonFreeman | 12:d1d21a2941ef | 145 | * void hb_cmd (struct parameters & a) // Hand brake command |
JonFreeman | 12:d1d21a2941ef | 146 | * Broadcast to all STM3_ESC boards, required to ACT but NOT respond |
JonFreeman | 12:d1d21a2941ef | 147 | * |
JonFreeman | 12:d1d21a2941ef | 148 | * NOTE Jan 2019 Hand brake not implemented |
JonFreeman | 16:d1e4b9ad3b8b | 149 | * May 2020 - Implemented, but not very good |
JonFreeman | 6:f289a49c1eae | 150 | */ |
JonFreeman | 12:d1d21a2941ef | 151 | void hb_cmd (struct parameters & a) // Hand brake command |
JonFreeman | 6:f289a49c1eae | 152 | { |
JonFreeman | 16:d1e4b9ad3b8b | 153 | double tmp; |
JonFreeman | 16:d1e4b9ad3b8b | 154 | if (a.numof_dbls != 0) tmp = a.dbl[0] / 100.0; // a.numof_dbls is int32_t |
JonFreeman | 16:d1e4b9ad3b8b | 155 | else tmp = 0.33; |
JonFreeman | 6:f289a49c1eae | 156 | if (a.respond) { |
JonFreeman | 16:d1e4b9ad3b8b | 157 | // a.com->printf ("numof params = %d\r\n", a.numof_dbls); |
JonFreeman | 16:d1e4b9ad3b8b | 158 | a.com->printf ("Hand Brake : Force 0 to 99 %.0f\r\n", tmp * 100.0); |
JonFreeman | 6:f289a49c1eae | 159 | } |
JonFreeman | 16:d1e4b9ad3b8b | 160 | mode_set_motors_both (MOTOR_HANDBRAKE); |
JonFreeman | 16:d1e4b9ad3b8b | 161 | if (tmp < 0.0) tmp = 0.0; |
JonFreeman | 16:d1e4b9ad3b8b | 162 | if (tmp > 1.0) tmp = 1.0; |
JonFreeman | 16:d1e4b9ad3b8b | 163 | setVI_both (tmp / 5.0, 0.99); |
JonFreeman | 6:f289a49c1eae | 164 | } |
JonFreeman | 6:f289a49c1eae | 165 | |
JonFreeman | 12:d1d21a2941ef | 166 | |
JonFreeman | 16:d1e4b9ad3b8b | 167 | |
JonFreeman | 16:d1e4b9ad3b8b | 168 | |
JonFreeman | 16:d1e4b9ad3b8b | 169 | /**void user_settings_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents |
JonFreeman | 16:d1e4b9ad3b8b | 170 | * user_settings_cmd called only from pc comms. No sense calling from Touch Screen Controller |
JonFreeman | 12:d1d21a2941ef | 171 | * |
JonFreeman | 12:d1d21a2941ef | 172 | * Called without parameters - Lists to pc terminal current settings |
JonFreeman | 12:d1d21a2941ef | 173 | * |
JonFreeman | 12:d1d21a2941ef | 174 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 175 | void user_settings_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents |
JonFreeman | 12:d1d21a2941ef | 176 | { |
JonFreeman | 16:d1e4b9ad3b8b | 177 | user_settings.edit (a.dbl, a.numof_dbls); |
JonFreeman | 16:d1e4b9ad3b8b | 178 | } |
JonFreeman | 16:d1e4b9ad3b8b | 179 | |
JonFreeman | 16:d1e4b9ad3b8b | 180 | extern struct optpar option_list[] ; //= { |
JonFreeman | 12:d1d21a2941ef | 181 | |
JonFreeman | 16:d1e4b9ad3b8b | 182 | void brake_eff_set_cmd (struct parameters & a) { // set brake effectiveness from TS May 2020 |
JonFreeman | 16:d1e4b9ad3b8b | 183 | char be = (char) a.dbl[0]; |
JonFreeman | 16:d1e4b9ad3b8b | 184 | pc.printf ("BRAKE_EFFECTIVENESS min = %d, max = %d\r\n", option_list[BRAKE_EFFECTIVENESS].min, option_list[BRAKE_EFFECTIVENESS].max); |
JonFreeman | 16:d1e4b9ad3b8b | 185 | if (be > option_list[BRAKE_EFFECTIVENESS].max) be = option_list[BRAKE_EFFECTIVENESS].max; |
JonFreeman | 16:d1e4b9ad3b8b | 186 | if (be < option_list[BRAKE_EFFECTIVENESS].min) be = option_list[BRAKE_EFFECTIVENESS].min; |
JonFreeman | 16:d1e4b9ad3b8b | 187 | user_settings.wr(be, BRAKE_EFFECTIVENESS); |
JonFreeman | 16:d1e4b9ad3b8b | 188 | user_settings.save (); |
JonFreeman | 16:d1e4b9ad3b8b | 189 | pc.printf ("Set brake effectiveness to %d pct\r\n", be); |
JonFreeman | 12:d1d21a2941ef | 190 | } |
JonFreeman | 12:d1d21a2941ef | 191 | |
JonFreeman | 16:d1e4b9ad3b8b | 192 | void ssl_cmd (struct parameters & a) { // set speed limit NEW and untested July 2019. Stored as speed * 10 to get 1dec place |
JonFreeman | 16:d1e4b9ad3b8b | 193 | char sp = (char) (a.dbl[0] * 10.0); |
JonFreeman | 16:d1e4b9ad3b8b | 194 | if (sp > option_list[TOP_SPEED].max) sp = option_list[TOP_SPEED].max; |
JonFreeman | 16:d1e4b9ad3b8b | 195 | if (sp < option_list[TOP_SPEED].min) sp = option_list[TOP_SPEED].min; |
JonFreeman | 16:d1e4b9ad3b8b | 196 | user_settings.wr(sp, TOP_SPEED); |
JonFreeman | 16:d1e4b9ad3b8b | 197 | user_settings.save (); |
JonFreeman | 16:d1e4b9ad3b8b | 198 | pc.printf ("Set speed limit to %.1f mph\r\n", a.dbl[0]); |
JonFreeman | 13:ef7a06fa11de | 199 | } |
JonFreeman | 13:ef7a06fa11de | 200 | |
JonFreeman | 12:d1d21a2941ef | 201 | /** |
JonFreeman | 12:d1d21a2941ef | 202 | * void temperature_cmd (struct parameters & a) { |
JonFreeman | 16:d1e4b9ad3b8b | 203 | * Few boards have temperature sensor fitted. Now only supports LM75B i2c sensor |
JonFreeman | 12:d1d21a2941ef | 204 | */ |
JonFreeman | 17:cc9b854295d6 | 205 | /*void read_temperature_cmd (struct parameters & a) { |
JonFreeman | 16:d1e4b9ad3b8b | 206 | float t = -99.25; |
JonFreeman | 6:f289a49c1eae | 207 | if (a.respond) { |
JonFreeman | 16:d1e4b9ad3b8b | 208 | a.com->printf ("tem%c ", user_settings.rd(BOARD_ID)); |
JonFreeman | 16:d1e4b9ad3b8b | 209 | if (read_temperature(t)) |
JonFreeman | 16:d1e4b9ad3b8b | 210 | a.com->printf ("Temperature = %7.3f\r\n", t); |
JonFreeman | 16:d1e4b9ad3b8b | 211 | else |
JonFreeman | 16:d1e4b9ad3b8b | 212 | a.com->printf ("Temp sensor not fitted\r\n"); |
JonFreeman | 6:f289a49c1eae | 213 | } |
JonFreeman | 17:cc9b854295d6 | 214 | }*/ |
JonFreeman | 6:f289a49c1eae | 215 | |
JonFreeman | 12:d1d21a2941ef | 216 | /** |
JonFreeman | 12:d1d21a2941ef | 217 | *void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors |
JonFreeman | 12:d1d21a2941ef | 218 | */ |
JonFreeman | 6:f289a49c1eae | 219 | void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors |
JonFreeman | 6:f289a49c1eae | 220 | { |
JonFreeman | 11:bfb73f083009 | 221 | if (a.respond) |
JonFreeman | 16:d1e4b9ad3b8b | 222 | // a.com->printf ("rpm%c %d %d\r%s", user_settings.rd(BOARD_ID), MotorA.RPM, MotorB.RPM, a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 16:d1e4b9ad3b8b | 223 | a.com->printf ("rpm%c %.0f %.0f\r%s", user_settings.rd(BOARD_ID), MotorA.dRPM, MotorB.dRPM, a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 6:f289a49c1eae | 224 | } |
JonFreeman | 6:f289a49c1eae | 225 | |
JonFreeman | 12:d1d21a2941ef | 226 | /** |
JonFreeman | 12:d1d21a2941ef | 227 | *void mph_cmd (struct parameters & a) // to report miles per hour |
JonFreeman | 12:d1d21a2941ef | 228 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 229 | void mph_cmd (struct parameters & a) // to report miles per hour to 1 decimal place - now 2dp May 2020 |
JonFreeman | 7:6deaeace9a3e | 230 | { |
JonFreeman | 16:d1e4b9ad3b8b | 231 | int j = 0; |
JonFreeman | 16:d1e4b9ad3b8b | 232 | double speedmph = 0.0; |
JonFreeman | 16:d1e4b9ad3b8b | 233 | if (MotorA.exists ()) { |
JonFreeman | 16:d1e4b9ad3b8b | 234 | j |= 1; |
JonFreeman | 16:d1e4b9ad3b8b | 235 | speedmph = MotorA.dMPH; |
JonFreeman | 16:d1e4b9ad3b8b | 236 | } |
JonFreeman | 16:d1e4b9ad3b8b | 237 | if (MotorB.exists ()) { |
JonFreeman | 16:d1e4b9ad3b8b | 238 | j |= 2; |
JonFreeman | 16:d1e4b9ad3b8b | 239 | speedmph += MotorB.dMPH; |
JonFreeman | 16:d1e4b9ad3b8b | 240 | } |
JonFreeman | 16:d1e4b9ad3b8b | 241 | if (j == 3) |
JonFreeman | 16:d1e4b9ad3b8b | 242 | speedmph /= 2.0; |
JonFreeman | 11:bfb73f083009 | 243 | if (a.respond) |
JonFreeman | 16:d1e4b9ad3b8b | 244 | // May 17th 2020 modified line below - removed superfluous cast, upped to 2 decimal places |
JonFreeman | 16:d1e4b9ad3b8b | 245 | // a.com->printf ("mph%c %.2f\r%s", user_settings.rd(BOARD_ID), speedmph, a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 16:d1e4b9ad3b8b | 246 | a.com->printf ("?s%c %.2f\r%s", user_settings.rd(BOARD_ID), speedmph, a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 12:d1d21a2941ef | 247 | } |
JonFreeman | 12:d1d21a2941ef | 248 | |
JonFreeman | 12:d1d21a2941ef | 249 | /** |
JonFreeman | 12:d1d21a2941ef | 250 | *void sysV_report (struct parameters & a) // to report system voltage |
JonFreeman | 12:d1d21a2941ef | 251 | * Reports system link voltage to one decimal place |
JonFreeman | 12:d1d21a2941ef | 252 | */ |
JonFreeman | 12:d1d21a2941ef | 253 | void sysV_report (struct parameters & a) // |
JonFreeman | 12:d1d21a2941ef | 254 | { |
JonFreeman | 12:d1d21a2941ef | 255 | if (a.respond) |
JonFreeman | 16:d1e4b9ad3b8b | 256 | a.com->printf ("?v%c %.1f\r%s", user_settings.rd(BOARD_ID), Read_BatteryVolts(), a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 7:6deaeace9a3e | 257 | } |
JonFreeman | 7:6deaeace9a3e | 258 | |
JonFreeman | 12:d1d21a2941ef | 259 | /** |
JonFreeman | 12:d1d21a2941ef | 260 | *void sysI_report (struct parameters & a) // to report motor currents |
JonFreeman | 12:d1d21a2941ef | 261 | * Reports doubles for each motor current amps to 2 decimal places |
JonFreeman | 12:d1d21a2941ef | 262 | */ |
JonFreeman | 12:d1d21a2941ef | 263 | void sysI_report (struct parameters & a) // |
JonFreeman | 12:d1d21a2941ef | 264 | { |
JonFreeman | 16:d1e4b9ad3b8b | 265 | if (a.respond) |
JonFreeman | 16:d1e4b9ad3b8b | 266 | a.com->printf ("?i%c %.2f %.2f\r%s", user_settings.rd(BOARD_ID), MotorA.Idbl, MotorB.Idbl, a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 12:d1d21a2941ef | 267 | } |
JonFreeman | 6:f289a49c1eae | 268 | |
JonFreeman | 16:d1e4b9ad3b8b | 269 | /* |
JonFreeman | 16:d1e4b9ad3b8b | 270 | |
JonFreeman | 16:d1e4b9ad3b8b | 271 | New December 2019 - possible for implementation |
JonFreeman | 16:d1e4b9ad3b8b | 272 | Having implemented radio control inputs and driver pot, there is some sense in moving slider handler from touch screen controller |
JonFreeman | 16:d1e4b9ad3b8b | 273 | into STM3_ESC code. |
JonFreeman | 16:d1e4b9ad3b8b | 274 | New instructions to be accepted from touch screen : - |
JonFreeman | 16:d1e4b9ad3b8b | 275 | {"w", "touch screen new slider touch", slider_touch_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 276 | {"x", "updated slider RANGE 0 to 99", slider_touch_position_cmd}, // max two digits |
JonFreeman | 16:d1e4b9ad3b8b | 277 | {"y", "touch_screen slider finger lifted clear", slider_untouch_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 278 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 279 | bool finger_on_slider = false; |
JonFreeman | 16:d1e4b9ad3b8b | 280 | /**void slider_touch_cmd (struct parameters & a) |
JonFreeman | 16:d1e4b9ad3b8b | 281 | * |
JonFreeman | 16:d1e4b9ad3b8b | 282 | * Message from touch screen controller, slider touched |
JonFreeman | 16:d1e4b9ad3b8b | 283 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 284 | void slider_touch_cmd (struct parameters & a) { |
JonFreeman | 16:d1e4b9ad3b8b | 285 | finger_on_slider = true; |
JonFreeman | 16:d1e4b9ad3b8b | 286 | } |
JonFreeman | 16:d1e4b9ad3b8b | 287 | |
JonFreeman | 16:d1e4b9ad3b8b | 288 | /**void slider_untouch_cmd (struct parameters & a) |
JonFreeman | 16:d1e4b9ad3b8b | 289 | * |
JonFreeman | 16:d1e4b9ad3b8b | 290 | * Message from touch screen controller, finger taken off slider |
JonFreeman | 16:d1e4b9ad3b8b | 291 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 292 | void slider_untouch_cmd (struct parameters & a) { |
JonFreeman | 16:d1e4b9ad3b8b | 293 | finger_on_slider = false; |
JonFreeman | 16:d1e4b9ad3b8b | 294 | } |
JonFreeman | 16:d1e4b9ad3b8b | 295 | |
JonFreeman | 16:d1e4b9ad3b8b | 296 | /**void slider_touch_position_cmd (struct parameters & a) |
JonFreeman | 16:d1e4b9ad3b8b | 297 | * |
JonFreeman | 16:d1e4b9ad3b8b | 298 | * Message from touch screen controller, latest slider touch position |
JonFreeman | 16:d1e4b9ad3b8b | 299 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 300 | void slider_touch_position_cmd (struct parameters & a) { |
JonFreeman | 16:d1e4b9ad3b8b | 301 | } |
JonFreeman | 16:d1e4b9ad3b8b | 302 | |
JonFreeman | 16:d1e4b9ad3b8b | 303 | // End of New December 2019 |
JonFreeman | 16:d1e4b9ad3b8b | 304 | |
JonFreeman | 12:d1d21a2941ef | 305 | |
JonFreeman | 12:d1d21a2941ef | 306 | /**void vi_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 307 | * |
JonFreeman | 12:d1d21a2941ef | 308 | * For setting motor voltage and current limits from pc terminal for test |
JonFreeman | 12:d1d21a2941ef | 309 | */ |
JonFreeman | 6:f289a49c1eae | 310 | void vi_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 311 | { |
JonFreeman | 16:d1e4b9ad3b8b | 312 | setVI_both (a.dbl[0] / 100.0, a.dbl[1] / 100.0); |
JonFreeman | 16:d1e4b9ad3b8b | 313 | // pc.printf ("setVI_both from %s\r\n", a.source == SOURCE_PC ? "PC" : "Touch Screen"); |
JonFreeman | 6:f289a49c1eae | 314 | } |
JonFreeman | 6:f289a49c1eae | 315 | |
JonFreeman | 12:d1d21a2941ef | 316 | /** |
JonFreeman | 12:d1d21a2941ef | 317 | *void v_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 318 | * Set motor voltage limit from either source without checking for addressed board |
JonFreeman | 12:d1d21a2941ef | 319 | */ |
JonFreeman | 6:f289a49c1eae | 320 | void v_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 321 | { |
JonFreeman | 12:d1d21a2941ef | 322 | MotorA.set_V_limit (a.dbl[0] / 100.0); |
JonFreeman | 12:d1d21a2941ef | 323 | MotorB.set_V_limit (a.dbl[0] / 100.0); |
JonFreeman | 6:f289a49c1eae | 324 | } |
JonFreeman | 6:f289a49c1eae | 325 | |
JonFreeman | 12:d1d21a2941ef | 326 | /** |
JonFreeman | 12:d1d21a2941ef | 327 | *void i_cmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 328 | * Set motor current limit from either source without checking for addressed board |
JonFreeman | 12:d1d21a2941ef | 329 | */ |
JonFreeman | 6:f289a49c1eae | 330 | void i_cmd (struct parameters & a) |
JonFreeman | 6:f289a49c1eae | 331 | { |
JonFreeman | 12:d1d21a2941ef | 332 | MotorA.set_I_limit (a.dbl[0] / 100.0); |
JonFreeman | 12:d1d21a2941ef | 333 | MotorB.set_I_limit (a.dbl[0] / 100.0); |
JonFreeman | 6:f289a49c1eae | 334 | } |
JonFreeman | 6:f289a49c1eae | 335 | |
JonFreeman | 12:d1d21a2941ef | 336 | /** |
JonFreeman | 12:d1d21a2941ef | 337 | *void kd_cmd (struct parameters & a) // kick and enable the watch dog |
JonFreeman | 12:d1d21a2941ef | 338 | * |
JonFreeman | 13:ef7a06fa11de | 339 | * Brute_TS_Controller or other external controller to issue regular 'kd\r' to come here. |
JonFreeman | 13:ef7a06fa11de | 340 | * WatchDog disabled by default, enabled on first call to here |
JonFreeman | 13:ef7a06fa11de | 341 | * This is where WatchDog timer is reset and reloaded. |
JonFreeman | 13:ef7a06fa11de | 342 | * Timeout may be detected and handled in 8Hz loop in main programme loop |
JonFreeman | 12:d1d21a2941ef | 343 | */ |
JonFreeman | 12:d1d21a2941ef | 344 | void kd_cmd (struct parameters & a) // kick the watchdog. Reached from TS or pc. |
JonFreeman | 6:f289a49c1eae | 345 | { |
JonFreeman | 16:d1e4b9ad3b8b | 346 | WatchDog = WATCHDOG_RELOAD + (user_settings.rd(BOARD_ID) & 0x0f); // Reload watchdog timeout. Counted down @ 8Hz |
JonFreeman | 12:d1d21a2941ef | 347 | WatchDogEnable = true; // Receipt of this command sufficient to enable watchdog |
JonFreeman | 6:f289a49c1eae | 348 | } |
JonFreeman | 6:f289a49c1eae | 349 | |
JonFreeman | 13:ef7a06fa11de | 350 | void wd_report (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS |
JonFreeman | 13:ef7a06fa11de | 351 | { |
JonFreeman | 13:ef7a06fa11de | 352 | pc.printf ("WatchDog %d\r\n", WatchDog); |
JonFreeman | 13:ef7a06fa11de | 353 | } |
JonFreeman | 12:d1d21a2941ef | 354 | /** |
JonFreeman | 12:d1d21a2941ef | 355 | *void who_cmd (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS |
JonFreeman | 12:d1d21a2941ef | 356 | * |
JonFreeman | 12:d1d21a2941ef | 357 | * When using STM3_ESC boards together with 'Brute Touch Screen Controller', controller needs to identify number and identity |
JonFreeman | 12:d1d21a2941ef | 358 | * of all connected STM3_ESC boards. To do this the Touch Screen issues '0who', '1who' ... '9who' allowing time between each |
JonFreeman | 12:d1d21a2941ef | 359 | * 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 | 360 | */ |
JonFreeman | 12:d1d21a2941ef | 361 | void who_cmd (struct parameters & a) // Reachable always from pc. Only addressed board responds to TS |
JonFreeman | 6:f289a49c1eae | 362 | { |
JonFreeman | 16:d1e4b9ad3b8b | 363 | if (a.source == SOURCE_PC || user_settings.rd(BOARD_ID) == a.target_unit) |
JonFreeman | 16:d1e4b9ad3b8b | 364 | a.com->printf ("who%c\r%s", user_settings.rd(BOARD_ID), a.source == SOURCE_PC ? "\n" : ""); |
JonFreeman | 6:f289a49c1eae | 365 | } |
JonFreeman | 6:f289a49c1eae | 366 | |
JonFreeman | 17:cc9b854295d6 | 367 | extern void rcins_report () ; |
JonFreeman | 17:cc9b854295d6 | 368 | void qrc_cmd (struct parameters & a) // report RC1 and RC2 input condition and activity |
JonFreeman | 17:cc9b854295d6 | 369 | { |
JonFreeman | 17:cc9b854295d6 | 370 | rcins_report (); |
JonFreeman | 17:cc9b854295d6 | 371 | } |
JonFreeman | 17:cc9b854295d6 | 372 | |
JonFreeman | 12:d1d21a2941ef | 373 | /** |
JonFreeman | 12:d1d21a2941ef | 374 | *void rcin_pccmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 375 | * |
JonFreeman | 12:d1d21a2941ef | 376 | * For test, reports to pc terminal info about radio control input channels |
JonFreeman | 12:d1d21a2941ef | 377 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 378 | //void rcin_pccmd (struct parameters & a) |
JonFreeman | 16:d1e4b9ad3b8b | 379 | //{ |
JonFreeman | 16:d1e4b9ad3b8b | 380 | // rcin_report (); |
JonFreeman | 16:d1e4b9ad3b8b | 381 | //} |
JonFreeman | 16:d1e4b9ad3b8b | 382 | /* |
JonFreeman | 12:d1d21a2941ef | 383 | void scmd (struct parameters & a) // filter coefficient fiddler |
JonFreeman | 12:d1d21a2941ef | 384 | { |
JonFreeman | 12:d1d21a2941ef | 385 | switch ((int)a.dbl[0]) { |
JonFreeman | 12:d1d21a2941ef | 386 | case 1: |
JonFreeman | 13:ef7a06fa11de | 387 | MotorA.sdbl[1] = MotorB.sdbl[1] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 388 | break; |
JonFreeman | 12:d1d21a2941ef | 389 | case 2: |
JonFreeman | 13:ef7a06fa11de | 390 | MotorA.sdbl[2] = MotorB.sdbl[2] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 391 | break; |
JonFreeman | 12:d1d21a2941ef | 392 | case 3: |
JonFreeman | 13:ef7a06fa11de | 393 | MotorA.sdbl[3] = MotorB.sdbl[3] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 394 | break; |
JonFreeman | 12:d1d21a2941ef | 395 | case 4: |
JonFreeman | 13:ef7a06fa11de | 396 | MotorA.sdbl[4] = MotorB.sdbl[4] = a.dbl[1]; |
JonFreeman | 12:d1d21a2941ef | 397 | break; |
JonFreeman | 12:d1d21a2941ef | 398 | default: |
JonFreeman | 12:d1d21a2941ef | 399 | pc.printf ("Wrong use of scmd %f\r\n", a.dbl[0]); |
JonFreeman | 12:d1d21a2941ef | 400 | } |
JonFreeman | 13:ef7a06fa11de | 401 | pc.printf ("Filter Coefficient Fiddler - used in brushless_motor::speed_monitor_and_control ()"); |
JonFreeman | 12:d1d21a2941ef | 402 | pc.printf ("Filter Coeffs 1 to 4\r\n"); |
JonFreeman | 13:ef7a06fa11de | 403 | pc.printf ("1 %.3f\tPscale 0.01-0.5\r\n", MotorA.sdbl[1]); |
JonFreeman | 13:ef7a06fa11de | 404 | pc.printf ("2 %.3f\tP_gain 1.0-1000.0\r\n", MotorA.sdbl[2]); |
JonFreeman | 13:ef7a06fa11de | 405 | pc.printf ("3 %.3f\tDscale 0.01-0.5\r\n", MotorA.sdbl[3]); |
JonFreeman | 13:ef7a06fa11de | 406 | pc.printf ("4 %.3f\tD_gain 1.0-1000.0\r\n", MotorA.sdbl[4]); |
JonFreeman | 16:d1e4b9ad3b8b | 407 | // pc.printf ("5 Set target_speed\r\n"); |
JonFreeman | 12:d1d21a2941ef | 408 | } |
JonFreeman | 16:d1e4b9ad3b8b | 409 | */ |
JonFreeman | 12:d1d21a2941ef | 410 | struct kb_command { // Commands tabulated as list of these structures as seen below |
JonFreeman | 12:d1d21a2941ef | 411 | const char * cmd_word; // points to text e.g. "menu" |
JonFreeman | 12:d1d21a2941ef | 412 | const char * explan; // very brief explanation or clue as to purpose of function |
JonFreeman | 12:d1d21a2941ef | 413 | void (*f)(struct parameters &); // points to function |
JonFreeman | 12:d1d21a2941ef | 414 | } ; // Positioned in code here as knowledge needed by following menucmd |
JonFreeman | 12:d1d21a2941ef | 415 | |
JonFreeman | 12:d1d21a2941ef | 416 | /** |
JonFreeman | 12:d1d21a2941ef | 417 | * void menucmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 418 | * |
JonFreeman | 12:d1d21a2941ef | 419 | * List available terminal commands to pc terminal. No sense in touch screen using this |
JonFreeman | 12:d1d21a2941ef | 420 | */ |
JonFreeman | 12:d1d21a2941ef | 421 | void menucmd (struct parameters & a) |
JonFreeman | 12:d1d21a2941ef | 422 | { |
JonFreeman | 12:d1d21a2941ef | 423 | if (a.respond) { |
JonFreeman | 16:d1e4b9ad3b8b | 424 | a.com->printf("\r\n\nDual BLDC ESC type STM3 2018-20, Ver %s\r\nAt menucmd function - listing commands, source %s:-\r\n", get_version(), a.source == SOURCE_PC ? "PC" : "TS"); |
JonFreeman | 12:d1d21a2941ef | 425 | for(int i = 0; i < a.numof_menu_items; i++) |
JonFreeman | 12:d1d21a2941ef | 426 | a.com->printf("[%s]\t\t%s\r\n", a.command_list[i].cmd_word, a.command_list[i].explan); |
JonFreeman | 12:d1d21a2941ef | 427 | a.com->printf("End of List of Commands\r\n"); |
JonFreeman | 12:d1d21a2941ef | 428 | } |
JonFreeman | 12:d1d21a2941ef | 429 | } |
JonFreeman | 12:d1d21a2941ef | 430 | |
JonFreeman | 12:d1d21a2941ef | 431 | /********************** END OF COMMAND LINE INTERPRETER COMMANDS *************************************/ |
JonFreeman | 6:f289a49c1eae | 432 | |
JonFreeman | 9:ac2412df01be | 433 | |
JonFreeman | 9:ac2412df01be | 434 | /** |
JonFreeman | 12:d1d21a2941ef | 435 | * struct kb_command const loco_command_list[] = { |
JonFreeman | 12:d1d21a2941ef | 436 | * List of commands accepted from external controller through opto isolated com port 19200, 8,n,1 |
JonFreeman | 9:ac2412df01be | 437 | */ |
JonFreeman | 12:d1d21a2941ef | 438 | struct kb_command const loco_command_list[] = { // For comms between STM3_ESC and 'Brute Touch Screen Controller' |
JonFreeman | 12:d1d21a2941ef | 439 | // ***** Broadcast commands for all STM3_ESC boards to execute. Boards NOT to send serial response ***** |
JonFreeman | 6:f289a49c1eae | 440 | {"fw", "forward", fw_cmd}, |
JonFreeman | 6:f289a49c1eae | 441 | {"re", "reverse", re_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 442 | {"rb", "regen brake 0 to 99 %", rb_cmd}, // max two digits |
JonFreeman | 6:f289a49c1eae | 443 | {"hb", "hand brake", hb_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 444 | {"v", "set motors V percent RANGE 0 to 99", v_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 445 | {"i", "set motors I percent RANGE 0 to 99", i_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 446 | {"vi", "set motors V and I percent RANGE 0 to 99", vi_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 447 | {"w", "touch screen new slider touch", slider_touch_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 448 | {"x", "updated slider RANGE 0 to 99", slider_touch_position_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 449 | {"y", "touch_screen slider finger lifted clear", slider_untouch_cmd}, |
JonFreeman | 12:d1d21a2941ef | 450 | {"kd", "kick the dog, reloads WatchDog", kd_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 451 | {"ssl", "set speed limit e.g. 10.7", ssl_cmd}, // NEW July 2019 |
JonFreeman | 16:d1e4b9ad3b8b | 452 | {"sbe", "set brake effectiveness 5 to 90 percent", brake_eff_set_cmd}, // NEW May 2020 |
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 | 17:cc9b854295d6 | 459 | // {"tem", "report temperature", read_temperature_cmd}, |
JonFreeman | 8:93203f473f6e | 460 | {"mph", "read loco speed miles per hour", mph_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 461 | {"?s", "read loco speed miles per hour", mph_cmd}, // Shorter-hand added 17th May 2020 |
JonFreeman | 16:d1e4b9ad3b8b | 462 | // {"ssl", "set speed limit e.g. 10.7", ssl_cmd}, // NEW July 2019 |
JonFreeman | 16:d1e4b9ad3b8b | 463 | // {"sbe", "set brake effectiveness 5 to 90 percent", brake_eff_set_cmd}, // NEW May 2020 |
JonFreeman | 12:d1d21a2941ef | 464 | // {"rvi", "read most recent values sent to pwms", rvi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 465 | // {"rdi", "read motor currents and power voltage", rdi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 466 | // ***** Endof |
JonFreeman | 12:d1d21a2941ef | 467 | } ; |
JonFreeman | 7:6deaeace9a3e | 468 | |
JonFreeman | 7:6deaeace9a3e | 469 | |
JonFreeman | 9:ac2412df01be | 470 | /** |
JonFreeman | 9:ac2412df01be | 471 | struct kb_command const loco_command_list[] = { |
JonFreeman | 9:ac2412df01be | 472 | List of commands accepted from external pc through non-opto isolated com port 9600, 8,n,1 |
JonFreeman | 9:ac2412df01be | 473 | */ |
JonFreeman | 7:6deaeace9a3e | 474 | struct kb_command const pc_command_list[] = { |
JonFreeman | 7:6deaeace9a3e | 475 | {"ls", "Lists available commands", menucmd}, |
JonFreeman | 7:6deaeace9a3e | 476 | {"?", "Lists available commands, same as ls", menucmd}, |
JonFreeman | 8:93203f473f6e | 477 | {"pot", "read drivers control pot", pot_cmd}, |
JonFreeman | 7:6deaeace9a3e | 478 | {"fw", "forward", fw_cmd}, |
JonFreeman | 7:6deaeace9a3e | 479 | {"re", "reverse", re_cmd}, |
JonFreeman | 7:6deaeace9a3e | 480 | {"rb", "regen brake 0 to 99 %", rb_cmd}, |
JonFreeman | 7:6deaeace9a3e | 481 | {"hb", "hand brake", hb_cmd}, |
JonFreeman | 7:6deaeace9a3e | 482 | {"v", "set motors V percent RANGE 0 to 100", v_cmd}, |
JonFreeman | 7:6deaeace9a3e | 483 | {"i", "set motors I percent RANGE 0 to 100", i_cmd}, |
JonFreeman | 7:6deaeace9a3e | 484 | {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 485 | {"?v", "Report system bus voltage", sysV_report}, |
JonFreeman | 12:d1d21a2941ef | 486 | {"?i", "Report motor both currents", sysI_report}, |
JonFreeman | 13:ef7a06fa11de | 487 | {"?w", "show WatchDog timer contents", wd_report}, |
JonFreeman | 17:cc9b854295d6 | 488 | {"kd", "kick the dog, reloads WatchDog", kd_cmd}, |
JonFreeman | 8:93203f473f6e | 489 | {"who", "search for connected units, e.g. 3who returs 'who3' if found", who_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 490 | {"us", "read or set user settings in eeprom", user_settings_cmd}, // Big change Jan 2019 |
JonFreeman | 13:ef7a06fa11de | 491 | {"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 | 16:d1e4b9ad3b8b | 492 | {"sbe", "set brake effectiveness 5 to 90 percent", brake_eff_set_cmd}, // NEW May 2020 |
JonFreeman | 12:d1d21a2941ef | 493 | // {"erase", "set eeprom contents to all 0xff", erase_cmd}, |
JonFreeman | 17:cc9b854295d6 | 494 | // {"tem", "report temperature", read_temperature_cmd}, // Reports -50 when sensor not fitted |
JonFreeman | 12:d1d21a2941ef | 495 | {"ver", "Version", ver_cmd}, |
JonFreeman | 7:6deaeace9a3e | 496 | {"rpm", "read motor pair speeds", rpm_cmd}, |
JonFreeman | 17:cc9b854295d6 | 497 | // {"mph", "read loco speed miles per hour", mph_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 498 | {"?s", "read loco speed miles per hour", mph_cmd}, |
JonFreeman | 17:cc9b854295d6 | 499 | {"?rc", "report RC1 and RC2 input condition and activity", qrc_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 500 | // {"rvi", "read most recent values sent to pwms", rvi_cmd}, |
JonFreeman | 16:d1e4b9ad3b8b | 501 | // {"rdi", "read motor currents and power voltage", rdi_cmd}, |
JonFreeman | 12:d1d21a2941ef | 502 | // {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd}, |
JonFreeman | 12:d1d21a2941ef | 503 | // {"gbb", "get bogie bytes from eeprom and report", gbb_cmd}, // OBSOLETE, replaced by 'gbb' |
JonFreeman | 7:6deaeace9a3e | 504 | {"nu", "do nothing", null_cmd}, |
JonFreeman | 12:d1d21a2941ef | 505 | } ; |
JonFreeman | 7:6deaeace9a3e | 506 | |
JonFreeman | 12:d1d21a2941ef | 507 | // cli_2019 (BufferedSerial * comport, kb_command const * list, int list_len, int source) { |
JonFreeman | 12:d1d21a2941ef | 508 | /** |
JonFreeman | 12:d1d21a2941ef | 509 | * cli_2019 pcc (&pc, pc_command_list, sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC) ; |
JonFreeman | 12:d1d21a2941ef | 510 | * cli_2019 tsc (&com2, loco_command_list, sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS) ; |
JonFreeman | 12:d1d21a2941ef | 511 | * |
JonFreeman | 12:d1d21a2941ef | 512 | * Instantiate two Command Line Interpreters, one for pc terminal and one for touch screen controller |
JonFreeman | 12:d1d21a2941ef | 513 | */ |
JonFreeman | 12:d1d21a2941ef | 514 | cli_2019 pcc (&pc, pc_command_list, sizeof(pc_command_list) / sizeof(kb_command), SOURCE_PC) ; |
JonFreeman | 12:d1d21a2941ef | 515 | cli_2019 tsc (&com2, loco_command_list, sizeof(loco_command_list) / sizeof(kb_command), SOURCE_TS) ; |
JonFreeman | 6:f289a49c1eae | 516 | |
JonFreeman | 6:f289a49c1eae | 517 | /* |
JonFreeman | 6:f289a49c1eae | 518 | New - March 2018 |
JonFreeman | 12:d1d21a2941ef | 519 | Using opto isolated serial port, paralleled up using same pair to multiple STM3_ESC boards running this code. |
JonFreeman | 6:f289a49c1eae | 520 | New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to. |
JonFreeman | 6:f289a49c1eae | 521 | Commands without prefix digit - broadcast to all units, all to obey but none to respond. |
JonFreeman | 6:f289a49c1eae | 522 | Only units recognising its address from prefix digit may respond. This avoids bus contention. |
JonFreeman | 6:f289a49c1eae | 523 | But for BROADCAST commands, '0' may respond on behalf of the group |
JonFreeman | 6:f289a49c1eae | 524 | */ |
JonFreeman | 12:d1d21a2941ef | 525 | |
JonFreeman | 12:d1d21a2941ef | 526 | /** |
JonFreeman | 12:d1d21a2941ef | 527 | * void cli_2019::test () { |
JonFreeman | 12:d1d21a2941ef | 528 | * |
JonFreeman | 12:d1d21a2941ef | 529 | * Daft check that class instantiation worked |
JonFreeman | 12:d1d21a2941ef | 530 | */ |
JonFreeman | 16:d1e4b9ad3b8b | 531 | void cli_2019::flush () { |
JonFreeman | 16:d1e4b9ad3b8b | 532 | // char ch; |
JonFreeman | 16:d1e4b9ad3b8b | 533 | while (a.com->readable()) |
JonFreeman | 16:d1e4b9ad3b8b | 534 | a.com->getc(); |
JonFreeman | 16:d1e4b9ad3b8b | 535 | //pc.printf ("At cli2019::test, source %d len %d,\r\n", a.source, a.numof_menu_items); |
JonFreeman | 12:d1d21a2941ef | 536 | } |
JonFreeman | 12:d1d21a2941ef | 537 | |
JonFreeman | 12:d1d21a2941ef | 538 | /** |
JonFreeman | 12:d1d21a2941ef | 539 | * void cli_2019::core () { |
JonFreeman | 12:d1d21a2941ef | 540 | * |
JonFreeman | 12:d1d21a2941ef | 541 | * Command Line Interpreter. |
JonFreeman | 12:d1d21a2941ef | 542 | * This to be called every few milli secs from main programme loop. |
JonFreeman | 12:d1d21a2941ef | 543 | * Reads any rx'd chars into command line buffer, returns when serial buffer empty. |
JonFreeman | 12:d1d21a2941ef | 544 | * 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 | 545 | * If matched command found, apt function is executed. |
JonFreeman | 12:d1d21a2941ef | 546 | * Parameters available to functions from 'parameters' struct. |
JonFreeman | 12:d1d21a2941ef | 547 | */ |
JonFreeman | 12:d1d21a2941ef | 548 | void cli_2019::core () { |
JonFreeman | 16:d1e4b9ad3b8b | 549 | int ch, IAm = user_settings.rd(BOARD_ID); |
JonFreeman | 7:6deaeace9a3e | 550 | char * pEnd;//, * cmd_line_ptr; |
JonFreeman | 7:6deaeace9a3e | 551 | while (a.com->readable()) { |
JonFreeman | 7:6deaeace9a3e | 552 | ch = a.com->getc(); |
JonFreeman | 12:d1d21a2941ef | 553 | if (clindex > MAX_CMD_LEN) { // trap out stupidly long command lines |
JonFreeman | 12:d1d21a2941ef | 554 | ESC_Error.set (FAULT_COM_LINE_LEN, 1); // Set FAULT_EEPROM bit 0 if 24LC64 problem |
JonFreeman | 7:6deaeace9a3e | 555 | a.com->printf ("Error!! Stupidly long cmd line\r\n"); |
JonFreeman | 12:d1d21a2941ef | 556 | clindex = 0; |
JonFreeman | 7:6deaeace9a3e | 557 | } |
JonFreeman | 11:bfb73f083009 | 558 | if(ch != '\r') { // was this the 'Enter' key? |
JonFreeman | 11:bfb73f083009 | 559 | if (ch != '\n') // Ignore line feeds |
JonFreeman | 12:d1d21a2941ef | 560 | cmdline[clindex++] = ch; // added char to command being assembled |
JonFreeman | 11:bfb73f083009 | 561 | } |
JonFreeman | 7:6deaeace9a3e | 562 | else { // key was CR, may or may not be command to lookup |
JonFreeman | 7:6deaeace9a3e | 563 | a.target_unit = BROADCAST; // Set to BROADCAST default once found command line '\r' |
JonFreeman | 12:d1d21a2941ef | 564 | cmdline_ptr = cmdline; |
JonFreeman | 12:d1d21a2941ef | 565 | cmdline[clindex] = 0; // null terminate command string |
JonFreeman | 12:d1d21a2941ef | 566 | if(clindex) { // If have got some chars to lookup |
JonFreeman | 7:6deaeace9a3e | 567 | int i, wrdlen; |
JonFreeman | 12:d1d21a2941ef | 568 | if (isdigit(cmdline[0])) { // Look for command with prefix digit |
JonFreeman | 12:d1d21a2941ef | 569 | cmdline_ptr++; // point past identified digit prefix |
JonFreeman | 12:d1d21a2941ef | 570 | a.target_unit = cmdline[0]; // '0' to '9' |
JonFreeman | 7:6deaeace9a3e | 571 | //com->printf ("Got prefix %c\r\n", cmd_line[0]); |
JonFreeman | 7:6deaeace9a3e | 572 | } |
JonFreeman | 7:6deaeace9a3e | 573 | for (i = 0; i < a.numof_menu_items; i++) { // Look for input match in command list |
JonFreeman | 12:d1d21a2941ef | 574 | wrdlen = strlen(commandlist[i].cmd_word); |
JonFreeman | 12:d1d21a2941ef | 575 | if(strncmp(commandlist[i].cmd_word, cmdline_ptr, wrdlen) == 0 && !isalpha(cmdline_ptr[wrdlen])) { // If match found |
JonFreeman | 16:d1e4b9ad3b8b | 576 | for (int k = 0; k < MAX_CLI_PARAMS; k++) { |
JonFreeman | 7:6deaeace9a3e | 577 | a.dbl[k] = 0.0; |
JonFreeman | 7:6deaeace9a3e | 578 | } |
JonFreeman | 7:6deaeace9a3e | 579 | a.position_in_list = i; |
JonFreeman | 7:6deaeace9a3e | 580 | a.numof_dbls = 0; |
JonFreeman | 16:d1e4b9ad3b8b | 581 | // pEnd = cmdline + clindex; // does indeed point to null terminator |
JonFreeman | 12:d1d21a2941ef | 582 | pEnd = cmdline_ptr + wrdlen; |
JonFreeman | 16:d1e4b9ad3b8b | 583 | // while (*pEnd) { // Assemble all numerics as doubles |
JonFreeman | 16:d1e4b9ad3b8b | 584 | while (*pEnd && a.numof_dbls < MAX_CLI_PARAMS) { // Assemble all numerics as doubles |
JonFreeman | 7:6deaeace9a3e | 585 | a.dbl[a.numof_dbls++] = strtod (pEnd, &pEnd); |
JonFreeman | 16:d1e4b9ad3b8b | 586 | while (*pEnd && (pEnd < cmdline + clindex) && *pEnd && !isdigit(*pEnd) && ('.' != *pEnd) && ('-' != *pEnd) && ('+' != *pEnd)) { // Can crash cli here with e.g. 'ls -l' |
JonFreeman | 7:6deaeace9a3e | 587 | pEnd++; |
JonFreeman | 16:d1e4b9ad3b8b | 588 | } // problem occurs with input such as "- ", or "-a", seemingly anything dodgy following a '-' or a '+' |
JonFreeman | 16:d1e4b9ad3b8b | 589 | if (((*pEnd == '-') || (*pEnd == '+')) &&(!isdigit(*(pEnd+1))) && ('.' !=*(pEnd+1))) |
JonFreeman | 16:d1e4b9ad3b8b | 590 | pEnd = cmdline + clindex; // fixed by aborting remainder of line |
JonFreeman | 7:6deaeace9a3e | 591 | } |
JonFreeman | 7:6deaeace9a3e | 592 | a.respond = a.resp_always; |
JonFreeman | 7:6deaeace9a3e | 593 | if (((a.target_unit == BROADCAST) && (IAm == '0')) || (IAm == a.target_unit)) |
JonFreeman | 7:6deaeace9a3e | 594 | a.respond = true; // sorted 26/4/18 |
JonFreeman | 7:6deaeace9a3e | 595 | // All boards to obey BROADCAST command, only specific board to obey number prefixed command |
JonFreeman | 7:6deaeace9a3e | 596 | if ((a.target_unit == BROADCAST) || (IAm == a.target_unit)) |
JonFreeman | 12:d1d21a2941ef | 597 | commandlist[i].f(a); // execute command if addressed to this unit |
JonFreeman | 7:6deaeace9a3e | 598 | i = a.numof_menu_items + 1; // to exit for loop |
JonFreeman | 7:6deaeace9a3e | 599 | } // end of match found |
JonFreeman | 7:6deaeace9a3e | 600 | } // End of for numof_menu_items |
JonFreeman | 12:d1d21a2941ef | 601 | if(i == a.numof_menu_items) { |
JonFreeman | 12:d1d21a2941ef | 602 | // a.com->printf("No Match Found for CMD [%s]\r\n", cmdline); |
JonFreeman | 12:d1d21a2941ef | 603 | pc.printf("No Match Found for CMD [%s]\r\n", cmdline); |
JonFreeman | 12:d1d21a2941ef | 604 | ESC_Error.set (FAULT_COM_LINE_NOMATCH, 1); // Set FAULT_EEPROM bit 0 if 24LC64 problem |
JonFreeman | 12:d1d21a2941ef | 605 | } |
JonFreeman | 7:6deaeace9a3e | 606 | } // End of If have got some chars to lookup |
JonFreeman | 12:d1d21a2941ef | 607 | clindex = 0; |
JonFreeman | 12:d1d21a2941ef | 608 | } // End of else key was CR, may or may not be command to lookup |
JonFreeman | 12:d1d21a2941ef | 609 | } // End of while (com->readable()) |
JonFreeman | 12:d1d21a2941ef | 610 | } // end of command line interpreter core function |
JonFreeman | 6:f289a49c1eae | 611 | |
JonFreeman | 6:f289a49c1eae | 612 |