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

Dependencies:   TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM

Committer:
JonFreeman
Date:
Mon Jan 14 16:39:41 2019 +0000
Revision:
12:a25bdf135348
Parent:
11:a573664b1a59
Child:
14:6bcec5ac21ca
Tidied, better documented, more OOP, interim release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JonFreeman 5:21a8ac83142c 1 //Loco_TS_2018
JonFreeman 4:67478861c670 2 #include "mbed.h"
JonFreeman 5:21a8ac83142c 3 #include "AsyncSerial.hpp"
JonFreeman 4:67478861c670 4 #include <cctype>
JonFreeman 4:67478861c670 5 #include "Electric_Loco.h"
JonFreeman 4:67478861c670 6 using namespace std;
JonFreeman 4:67478861c670 7
JonFreeman 4:67478861c670 8 const int BROADCAST = '\r';
JonFreeman 4:67478861c670 9
JonFreeman 4:67478861c670 10 // WithOUT RTOS
JonFreeman 4:67478861c670 11 extern Serial pc;
JonFreeman 12:a25bdf135348 12 extern AsyncSerial com2escs;
JonFreeman 12:a25bdf135348 13 extern error_handling_Jan_2019 Controller_Error ;
JonFreeman 12:a25bdf135348 14 extern const char const_version_string[] ; // Version string, readable from serial ports
JonFreeman 4:67478861c670 15
JonFreeman 12:a25bdf135348 16 extern STM3_ESC_Interface My_STM3_ESC_boards ;
JonFreeman 12:a25bdf135348 17
JonFreeman 12:a25bdf135348 18 /*genio::genio (int dtype, int dlen) { // constructor
JonFreeman 11:a573664b1a59 19 d_type = dtype;
JonFreeman 11:a573664b1a59 20 d_len = dlen;
JonFreeman 11:a573664b1a59 21 for (int i = 0; i < MAX_PARAMS; i++) {
JonFreeman 12:a25bdf135348 22 si[i] = 0;
JonFreeman 11:a573664b1a59 23 dbl[i] = 0.0;
JonFreeman 11:a573664b1a59 24 }
JonFreeman 12:a25bdf135348 25 count = 0; // running total of times called
JonFreeman 12:a25bdf135348 26 available = false; // bool
JonFreeman 12:a25bdf135348 27 //available = 0; // if using integer rather than bool
JonFreeman 11:a573664b1a59 28 }
JonFreeman 11:a573664b1a59 29
JonFreeman 12:a25bdf135348 30 void genio::store (struct parameters & a) { // copies up to MAX_PARAMS into int and double arrays
JonFreeman 12:a25bdf135348 31 count++; // number of times this response rec'd this session
JonFreeman 11:a573664b1a59 32 available = true;
JonFreeman 12:a25bdf135348 33 for (int i = 0; i < d_len; i++) { // dlen // loaded on setup indicating expected num of parameters to handle. Why not just use MAX_PARAMS ?
JonFreeman 12:a25bdf135348 34 si[i] = (int32_t)a.dbl[i];
JonFreeman 11:a573664b1a59 35 dbl[i] = a.dbl[i];
JonFreeman 11:a573664b1a59 36 }
JonFreeman 11:a573664b1a59 37 }
JonFreeman 11:a573664b1a59 38
JonFreeman 12:a25bdf135348 39 bool genio::read (int32_t ** addr) {
JonFreeman 11:a573664b1a59 40 if (!available)
JonFreeman 11:a573664b1a59 41 return false;
JonFreeman 11:a573664b1a59 42 available = false;
JonFreeman 12:a25bdf135348 43 *addr = si; // int32_t ui[MAX_PARAMS];
JonFreeman 11:a573664b1a59 44 return true;
JonFreeman 11:a573664b1a59 45 }
JonFreeman 12:a25bdf135348 46 */
JonFreeman 12:a25bdf135348 47
JonFreeman 12:a25bdf135348 48 command_line_interpreter_core::command_line_interpreter_core (int p, int menulen, struct kb_command const * clistp) {
JonFreeman 12:a25bdf135348 49 clist = clistp;
JonFreeman 12:a25bdf135348 50 a.numof_menu_items = menulen;
JonFreeman 12:a25bdf135348 51 a.numof_cl_values_read = 0;
JonFreeman 12:a25bdf135348 52 portio = p;
JonFreeman 12:a25bdf135348 53 cl_index = 0;
JonFreeman 12:a25bdf135348 54 }
JonFreeman 12:a25bdf135348 55
JonFreeman 12:a25bdf135348 56 int command_line_interpreter_core::clreadable () {
JonFreeman 12:a25bdf135348 57 if (portio == 0)
JonFreeman 12:a25bdf135348 58 return pc.readable();
JonFreeman 12:a25bdf135348 59 return com2escs.readable();
JonFreeman 12:a25bdf135348 60 }
JonFreeman 12:a25bdf135348 61
JonFreeman 12:a25bdf135348 62 void command_line_interpreter_core::clputc (int c) {
JonFreeman 12:a25bdf135348 63 if (portio == 0)
JonFreeman 12:a25bdf135348 64 pc.putc (c);
JonFreeman 12:a25bdf135348 65 else
JonFreeman 12:a25bdf135348 66 com2escs.putc (c);
JonFreeman 12:a25bdf135348 67 }
JonFreeman 12:a25bdf135348 68
JonFreeman 12:a25bdf135348 69 int command_line_interpreter_core::clgetc () {
JonFreeman 12:a25bdf135348 70 if (portio == 0)
JonFreeman 12:a25bdf135348 71 return pc.getc();
JonFreeman 12:a25bdf135348 72 return com2escs.getc();
JonFreeman 12:a25bdf135348 73 }
JonFreeman 12:a25bdf135348 74
JonFreeman 11:a573664b1a59 75
JonFreeman 5:21a8ac83142c 76 void null_cmd (struct parameters & a)
JonFreeman 5:21a8ac83142c 77 {
JonFreeman 4:67478861c670 78 pc.printf ("At null_cmd, parameters : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
JonFreeman 4:67478861c670 79 }
JonFreeman 4:67478861c670 80
JonFreeman 4:67478861c670 81 void menucmd (struct parameters & a);
JonFreeman 4:67478861c670 82
JonFreeman 4:67478861c670 83 void kd_cmd (struct parameters & a) // kick the watchdog
JonFreeman 4:67478861c670 84 {
JonFreeman 4:67478861c670 85 }
JonFreeman 4:67478861c670 86
JonFreeman 11:a573664b1a59 87 void upmph_cmd (struct parameters & a) // controller rec'd mph from driver boards
JonFreeman 11:a573664b1a59 88 {
JonFreeman 12:a25bdf135348 89 My_STM3_ESC_boards.mph_update (a.dbl[1]);
JonFreeman 5:21a8ac83142c 90 }
JonFreeman 5:21a8ac83142c 91
JonFreeman 4:67478861c670 92
JonFreeman 12:a25bdf135348 93 void TSver_cmd (struct parameters & a) // Report current TS software version to pc
JonFreeman 4:67478861c670 94 {
JonFreeman 12:a25bdf135348 95 pc.printf ("ver %s\r\n", const_version_string);
JonFreeman 12:a25bdf135348 96 }
JonFreeman 12:a25bdf135348 97
JonFreeman 12:a25bdf135348 98 void boards_cmd (struct parameters & a) {
JonFreeman 12:a25bdf135348 99 int boards[MAX_ESCS], count = 0;
JonFreeman 12:a25bdf135348 100 My_STM3_ESC_boards.get_boards_list (boards);
JonFreeman 12:a25bdf135348 101 while (boards[count] && count < MAX_ESCS)
JonFreeman 12:a25bdf135348 102 count++;
JonFreeman 12:a25bdf135348 103 pc.printf ("Board Count = %d\r\n", count);
JonFreeman 12:a25bdf135348 104 if (count) {
JonFreeman 12:a25bdf135348 105 pc.printf ("Boards found ^");
JonFreeman 12:a25bdf135348 106 for (int i = 0; i < count; i++)
JonFreeman 12:a25bdf135348 107 pc.printf ("%c ", boards[i]);
JonFreeman 12:a25bdf135348 108 pc.printf ("\r\n");
JonFreeman 12:a25bdf135348 109 }
JonFreeman 12:a25bdf135348 110 else
JonFreeman 12:a25bdf135348 111 pc.printf ("No STM3_ESC boards found\r\n");
JonFreeman 12:a25bdf135348 112 }
JonFreeman 12:a25bdf135348 113
JonFreeman 12:a25bdf135348 114 void who_cmd (struct parameters & a) // Have read "whon" back from STM3_ESC where 'n' is STM3_Esc board ID number (ascii digit)
JonFreeman 12:a25bdf135348 115 {
JonFreeman 12:a25bdf135348 116 int v = (int)a.dbl[0] | '0';
JonFreeman 12:a25bdf135348 117 if (a.numof_cl_values_read == 1 && isdigit(v)) {
JonFreeman 12:a25bdf135348 118 // pc.printf ("who%c, vals read %d\r\n", (int)a.dbl[0] | '0', a.numof_cl_values_read);
JonFreeman 12:a25bdf135348 119 My_STM3_ESC_boards.set_board_ID (v);// set_board_id (v); // just to test and prove can not add same board twice
JonFreeman 12:a25bdf135348 120 }
JonFreeman 12:a25bdf135348 121 else
JonFreeman 12:a25bdf135348 122 pc.printf ("Garbage response to 'who', numof vals %d, value %c\r\n", a.numof_cl_values_read, v);
JonFreeman 12:a25bdf135348 123 }
JonFreeman 12:a25bdf135348 124
JonFreeman 12:a25bdf135348 125 void ver_req_cmd (struct parameters & a) // Touch Screen controller requesting version string from one specific ESC board
JonFreeman 12:a25bdf135348 126 {
JonFreeman 12:a25bdf135348 127 pc.printf ("ver_req_cmd not yet implemented\r\n");
JonFreeman 12:a25bdf135348 128 }
JonFreeman 4:67478861c670 129
JonFreeman 4:67478861c670 130 struct kb_command {
JonFreeman 4:67478861c670 131 const char * cmd_word; // points to text e.g. "menu"
JonFreeman 4:67478861c670 132 const char * explan;
JonFreeman 4:67478861c670 133 void (*f)(struct parameters &); // points to function
JonFreeman 4:67478861c670 134 } ;
JonFreeman 4:67478861c670 135
JonFreeman 4:67478861c670 136 struct kb_command const command_list[] = {
JonFreeman 4:67478861c670 137 {"ls", "Lists available commands", menucmd},
JonFreeman 4:67478861c670 138 {"?", "Lists available commands, same as ls", menucmd},
JonFreeman 12:a25bdf135348 139 {"ver", "report const_version_string", TSver_cmd}, // Report TS controller version
JonFreeman 12:a25bdf135348 140 {"boards", "List STM3_ESC boards connected", boards_cmd},
JonFreeman 4:67478861c670 141 {"kd", "kick the dog", kd_cmd},
JonFreeman 4:67478861c670 142 {"nu", "do nothing", null_cmd},
JonFreeman 4:67478861c670 143 };
JonFreeman 4:67478861c670 144
JonFreeman 5:21a8ac83142c 145 struct kb_command const loco_command_list[] = {
JonFreeman 5:21a8ac83142c 146 {"ls", "Lists available commands", menucmd},
JonFreeman 5:21a8ac83142c 147 {"?", "Lists available commands, same as ls", menucmd},
JonFreeman 12:a25bdf135348 148 {"who", "Reads 'whon' response from STM3_ESC where 'n' is board num ascii from eeprom", who_cmd},
JonFreeman 12:a25bdf135348 149 {"ver", "report const_version_string", ver_req_cmd}, // Request software version of one specific ESC board
JonFreeman 11:a573664b1a59 150 {"mph", "bogie mph reading", upmph_cmd}, // 22/06/2018
JonFreeman 5:21a8ac83142c 151 {"nu", "do nothing", null_cmd},
JonFreeman 5:21a8ac83142c 152 } ;
JonFreeman 5:21a8ac83142c 153
JonFreeman 5:21a8ac83142c 154
JonFreeman 12:a25bdf135348 155 void menucmd (struct parameters & a)
JonFreeman 5:21a8ac83142c 156 {
JonFreeman 12:a25bdf135348 157 pc.printf("\r\n\nTS_2018 Locomotive Touch Screen Controller\r\nAt menucmd function - listing commands:-\r\n");
JonFreeman 12:a25bdf135348 158 for(int i = 0; i < a.numof_menu_items; i++)
JonFreeman 12:a25bdf135348 159 pc.printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan);
JonFreeman 12:a25bdf135348 160 pc.printf("End of List of Commands\r\n");
JonFreeman 5:21a8ac83142c 161 }
JonFreeman 5:21a8ac83142c 162
JonFreeman 4:67478861c670 163
JonFreeman 12:a25bdf135348 164 /**
JonFreeman 4:67478861c670 165 New - March 2018
JonFreeman 4:67478861c670 166 Using opto isolated serial port, paralleled up using same pair to multiple boards running this code.
JonFreeman 4:67478861c670 167 New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to.
JonFreeman 4:67478861c670 168 Commands without prefix digit - broadcast to all units, none to respond.
JonFreeman 4:67478861c670 169 Only units recognising its address from prefix digit may respond. This avoids bus contention.
JonFreeman 4:67478861c670 170 But for BROADCAST commands, '0' may respond on behalf of the group
JonFreeman 4:67478861c670 171 */
JonFreeman 12:a25bdf135348 172 command_line_interpreter_core pcli (0, sizeof(command_list) / sizeof(kb_command), command_list);
JonFreeman 12:a25bdf135348 173 command_line_interpreter_core ploco (1, sizeof(loco_command_list) / sizeof(kb_command), loco_command_list);
JonFreeman 12:a25bdf135348 174
JonFreeman 12:a25bdf135348 175 void command_line_interpreter_core::sniff () { // look for recieved commands and act upon them
JonFreeman 5:21a8ac83142c 176 int ch;
JonFreeman 12:a25bdf135348 177 char * pEnd;
JonFreeman 12:a25bdf135348 178 while (clreadable()) {
JonFreeman 12:a25bdf135348 179 ch = clgetc ();
JonFreeman 12:a25bdf135348 180 if(ch != '\r') {// was this the 'Enter' key?
JonFreeman 12:a25bdf135348 181 if (ch != '\n') { // Ignore line feeds
JonFreeman 12:a25bdf135348 182 cmd_line[cl_index++] = ch; // added char to command being assembled
JonFreeman 12:a25bdf135348 183 if (cl_index >= MAX_CMD_LINE_LEN-2) {
JonFreeman 12:a25bdf135348 184 cl_index = 0; // Line is garbage anyway, so might as well junk the lot ?
JonFreeman 12:a25bdf135348 185 pc.printf ("cl_index=%d TOO LONG in clicore\r\n", cl_index);
JonFreeman 12:a25bdf135348 186 Controller_Error.set (FAULT_COM_LINE_LEN, 1);
JonFreeman 12:a25bdf135348 187 }
JonFreeman 12:a25bdf135348 188 } // endof if(ch != '\n') ignore line feeds
JonFreeman 12:a25bdf135348 189 } // endof if(ch != '\r')
JonFreeman 5:21a8ac83142c 190 else { // key was CR, may or may not be command to lookup
JonFreeman 12:a25bdf135348 191 target_unit = BROADCAST; // Broadcast
JonFreeman 5:21a8ac83142c 192 cmd_line_ptr = cmd_line;
JonFreeman 5:21a8ac83142c 193 cmd_line[cl_index] = 0; // null terminate command string
JonFreeman 5:21a8ac83142c 194 if(cl_index) { // If have got some chars to lookup
JonFreeman 5:21a8ac83142c 195 int i, wrdlen;
JonFreeman 5:21a8ac83142c 196 if (isdigit(cmd_line[0])) { // Look for command with prefix digit
JonFreeman 5:21a8ac83142c 197 cmd_line_ptr++; // point past identified digit prefix
JonFreeman 12:a25bdf135348 198 target_unit = cmd_line[0]; // '0' to '9'
JonFreeman 12:a25bdf135348 199 //pc.printf ("Got prefix %c\r\n", a.cmd_line[0]);
JonFreeman 5:21a8ac83142c 200 }
JonFreeman 12:a25bdf135348 201 for (i = 0; i < a.numof_menu_items; i++) { // Look for input match in command list
JonFreeman 12:a25bdf135348 202 wrdlen = strlen(clist[i].cmd_word);
JonFreeman 12:a25bdf135348 203 if(strncmp(clist[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(cmd_line_ptr[wrdlen])) { // If match found
JonFreeman 5:21a8ac83142c 204 for (int k = 0; k < MAX_PARAMS; k++) {
JonFreeman 12:a25bdf135348 205 a.dbl[k] = 0.0;
JonFreeman 5:21a8ac83142c 206 }
JonFreeman 12:a25bdf135348 207 //position_in_list = i;
JonFreeman 12:a25bdf135348 208 a.numof_cl_values_read = 0;
JonFreeman 5:21a8ac83142c 209 pEnd = cmd_line_ptr + wrdlen;
JonFreeman 5:21a8ac83142c 210 while (*pEnd) { // Assemble all numerics as doubles
JonFreeman 12:a25bdf135348 211 a.dbl[a.numof_cl_values_read++] = strtod (pEnd, &pEnd);
JonFreeman 5:21a8ac83142c 212 while (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd) {
JonFreeman 5:21a8ac83142c 213 pEnd++;
JonFreeman 4:67478861c670 214 }
JonFreeman 5:21a8ac83142c 215 }
JonFreeman 5:21a8ac83142c 216 //pc.printf ("\r\n"); // Not allowed as many may output this.
JonFreeman 12:a25bdf135348 217 //for (int k = 0; k < param_block.a.numof_cl_values_read; k++)
JonFreeman 5:21a8ac83142c 218 // pc.printf ("Read %.3f\r\n", param_block.dbl[k]);
JonFreeman 4:67478861c670 219 // param_block.times[i] = clock();
JonFreeman 4:67478861c670 220 // if ((param_block.target_unit == BROADCAST) && (I_Am() == '0'))
JonFreeman 4:67478861c670 221 // param_block.respond = true;
JonFreeman 12:a25bdf135348 222 clist[i].f(a); // execute command
JonFreeman 12:a25bdf135348 223 i = a.numof_menu_items + 1; // to exit for loop
JonFreeman 5:21a8ac83142c 224 } // end of match found
JonFreeman 5:21a8ac83142c 225 } // End of for numof_menu_items
JonFreeman 12:a25bdf135348 226 if(i == a.numof_menu_items) {
JonFreeman 5:21a8ac83142c 227 pc.printf("No Match Found for CMD [%s]\r\n", cmd_line);
JonFreeman 12:a25bdf135348 228 Controller_Error.set (FAULT_COM_NO_MATCH, 1);
JonFreeman 12:a25bdf135348 229 }
JonFreeman 5:21a8ac83142c 230 } // End of If have got some chars to lookup
JonFreeman 5:21a8ac83142c 231 cl_index = 0;
JonFreeman 5:21a8ac83142c 232 } // End of else key was CR, may or may not be command to lookup
JonFreeman 5:21a8ac83142c 233 } // End of while (pc.readable())
JonFreeman 12:a25bdf135348 234 }
JonFreeman 4:67478861c670 235
JonFreeman 12:a25bdf135348 236