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
Revision 6:f289a49c1eae, committed 2018-06-05
- Comitter:
- JonFreeman
- Date:
- Tue Jun 05 07:19:39 2018 +0000
- Parent:
- 5:ca86a7848d54
- Child:
- 7:6deaeace9a3e
- Commit message:
- Migrating towards code for both STM32F401RET (64 pin) and STM32F446ZET7 (144 pin). Should resolve IO conflicts for larger device - getting servo ins and outs working
Changed in this revision
--- a/DualBLS.h Tue May 29 16:36:34 2018 +0000 +++ b/DualBLS.h Tue Jun 05 07:19:39 2018 +0000 @@ -21,6 +21,7 @@ const double PI = 4.0 * atan(1.0), TWOPI = 8.0 * atan(1.0); +enum {MOTADIR, MOTBDIR, GANG, SVO1, SVO2, COMM_SRC, ID, WHEELDIA, MOTPIN, WHEELGEAR} ; // Identical in TS and DualBLS struct optpar { int min, max, def; // min, max, default const char * t; // description @@ -33,6 +34,12 @@ {0, 2, 2, "Servo2 0, 1, 2 = Not used, Input, Output"}, {1, 5, 2, "Command source 0 Invalid, 1 COM1, 2 COM2, 3 Pot, 4 Servo1, 5 Servo2"}, {'1', '9', '0', "Alternative ID ascii '1' to '9'"}, // defaults to '0' before eerom setup for first time + {50, 250, 98, "Wheel diameter mm"}, // New 01/06/2018 + {10, 250, 27, "Motor pinion"}, // New 01/06/2018 + {50, 250, 85, "Wheel gear"}, // New 01/06/2018 } ; -const int numofopts = sizeof(option_list) / sizeof (struct optpar); +const int numof_eeprom_options = sizeof(option_list) / sizeof (struct optpar); +struct single_bogie_options { + char motoradir, motorbdir, gang, svo1, svo2, comm_src, id, wheeldia, motpin, wheelgear, spare; +} ;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cli_BLS_nortos.cpp Tue Jun 05 07:19:39 2018 +0000 @@ -0,0 +1,334 @@ +// DualBLS2018_03 +#include "mbed.h" +#include "BufferedSerial.h" + +#include <cctype> +#include "DualBLS.h" +using namespace std; + +extern int I_Am () ; // Returns boards id number as ASCII char '0', '1' etc. Code for Broadcast = '\r' +extern int WatchDog; + +const int BROADCAST = '\r'; +const int MAX_PARAMS = 20; +struct parameters { + int32_t position_in_list, // set but not used Apr 2018, contains i for i'th menu item +// last_time, // gets reading from clock() ; not known to be useful or reliable + numof_dbls, + target_unit; + double dbl[MAX_PARAMS]; + bool respond; +} ; + +// WithOUT RTOS +extern BufferedSerial com2, pc; +extern void send_test () ; +extern void setVI (double v, double i) ; +extern void setV (double v) ; +extern void setI (double i) ; +extern void read_last_VI (double * val) ; // only for test from cli + +BufferedSerial * com; + +void null_cmd (struct parameters & a) +{ + if (a.respond) + com->printf ("At null_cmd, board ID %c, parameters : First %.3f, second %.3f\r\n", I_Am(), a.dbl[0], a.dbl[1]); +} + +extern void mode_set (int mode, double val) ; // called from cli to set fw, re, rb, hb +extern void read_supply_vi (double * val) ; + +void rdi_cmd (struct parameters & a) // read motor currents +{ + if (a.respond) { + double r[4]; + read_supply_vi (r); // get MotorA.I.ave, MotorB.I.ave, Battery volts + com->printf ("rdi%.0f %.0f %.1f\r", r[0], r[1], r[2]); // Format good to be unpicked by cli in touch screen controller + } +} + +void rvi_cmd (struct parameters & a) // read last normalised values sent to pwms +{ + if (a.respond) { + double r[6]; + read_last_VI (r); + com->printf ("rvi%.2f %.2f %.2f %.2f\r", r[0], r[1], r[2], r[3]); + } +} + +void fw_cmd (struct parameters & a) // Forward command +{ + mode_set (FORWARD, 0.0); +} + +void re_cmd (struct parameters & a) // Reverse command +{ + mode_set (REVERSE, 0.0); +} + +void rb_cmd (struct parameters & a) // Regen brake command +{ + double b = a.dbl[0] / 100.0; +// com->printf ("Applying brake %.3f\r\n", b); + mode_set (REGENBRAKE, b); +// apply_brake (b); +} + +extern bool wr_24LC64 (int mem_start_addr, char * source, int length) ; +extern bool rd_24LC64 (int mem_start_addr, char * dest, int length) ; + +void erase_cmd (struct parameters & a) // Sets eeprom contents to all 0xff. 256 pages of 32 bytes to do +{ + char t[36]; + for (int i = 0; i < 32; i++) + t[i] = 0xff; + for (int i = 0; i < 8191; i += 32) { + com->printf ("."); + if (!wr_24LC64 (i, t, 32)) + com->printf ("eeprom write prob\r\n"); + } +} +/*struct motorpairoptions { // This to be user settable in eeprom, 32 bytes + uint8_t MotA_dir, // 0 or 1 + MotB_dir, // 0 or 1 + gang, // 0 for separate control (robot mode), 1 for ganged loco bogie mode + serv1, // 0, 1, 2 = Not used, Input, Output + serv2, // 0, 1, 2 = Not used, Input, Output + cmd_source, // 0 Invalid, 1 COM1, 2 COM2, 3 Pot, 4 Servo1, 5 Servo2 + {'1', '9', '0', "Alternative ID ascii '1' to '9'"}, // defaults to '0' before eerom setup for first time + {50, 250, 98, "Wheel diameter mm"}, // New 01/06/2018 + {10, 250, 27, "Motor pinion"}, // New 01/06/2018 + {50, 250, 85, "Wheel gear"}, // New 01/06/2018 +// last; +} ; +*/ +extern char mode_bytes[]; + +void mode_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents +{ + if (a.target_unit == BROADCAST) { +// com->printf ("At mode_cmd, can not use BROADCAST with mode_cmd\r\n"); + } else { + char t[36]; + com->printf ("At mode_cmd with node %d\r\n", a.target_unit); + rd_24LC64 (0, t, 32); + com->printf ("Numof params=%d\r\n", a.numof_dbls); + for (int i = 0; i < numof_eeprom_options; i++) + com->printf ("%2x\t%s\r\n", t[i], option_list[i].t); + if (a.numof_dbls == 0) { // Read present contents, do not write + com->printf ("That's it\r\n"); + } else { // Write new shit to eeprom + com->printf ("\r\n"); + if (a.numof_dbls != numof_eeprom_options) { + com->printf ("params required = %d, you offered %d\r\n", numof_eeprom_options, a.numof_dbls); + } else { // Have been passed correct number of parameters + int b; + com->printf("Ready to write params to eeprom\r\n"); + for (int i = 0; i < numof_eeprom_options; i++) { + b = (int)a.dbl[i]; // parameter value to check against limits + if (i == 6) // Alternative ID must be turned to ascii + b |= '0'; + if ((b < option_list[i].min) || (b > option_list[i].max)) { // if parameter out of range + com->printf("Warning - Parameter = %d, out of range, setting to default %d\r\n", b, option_list[i].def); + b = option_list[i].def; + } + com->printf ("0x%2x\t%s\r\n", (t[i] = b), option_list[i].t); + } + wr_24LC64 (0, t, numof_eeprom_options); + memcpy (mode_bytes,t,32); + com->printf("Parameters set in eeprom\r\n"); + } + } + } +} +/*void coast_cmd (struct parameters & a) { // Coast + +} +*/ +void hb_cmd (struct parameters & a) +{ + if (a.respond) { + com->printf ("numof params = %d\r\n", a.numof_dbls); + com->printf ("Hand Brake : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]); + } + mode_set (HANDBRAKE, 0.0); +} + +extern uint32_t last_temp_count; +void temperature_cmd (struct parameters & a) { + if (a.respond) { + com->printf ("tem%c %d\r\n", mode_bytes[ID], (last_temp_count / 16) - 50); + } +} + +void bogie_constants_report_cmd (struct parameters & a) { + if (a.respond) { + com->printf ("bc%c %d %d %d\r\n", mode_bytes[ID], mode_bytes[WHEELDIA], mode_bytes[MOTPIN], mode_bytes[WHEELGEAR]); + } +} + +extern void read_RPM (uint32_t * dest) ; +void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors +{ + if (a.respond) { + uint32_t dest[3]; + read_RPM (dest); + com->printf ("rpm%d %d\r", dest[0], dest[1]); + } +} + +void menucmd (struct parameters & a); + +void vi_cmd (struct parameters & a) +{ +// if (a.respond) +// com->printf ("In setVI, setting V to %.2f, I %.2f\r\n", a.dbl[0], a.dbl[1]); + setVI (a.dbl[0] / 100.0, a.dbl[1] / 100.0); +} + +void v_cmd (struct parameters & a) +{ +// if (a.respond) +// com->printf ("In setV, setting V to %.2f\r\n", a.dbl[0]); + setV (a.dbl[0] / 100.0); +} + +void i_cmd (struct parameters & a) +{ +// if (a.respond) +// com->printf ("In setI, setting I to %.2f\r\n", a.dbl[0]); + setI (a.dbl[0] / 100.0); +} + +void kd_cmd (struct parameters & a) // kick the watchdog +{ + WatchDog = WATCHDOG_RELOAD + (I_Am() & 0x0f); +// com->printf ("Poked %d up Dog\r\n", WatchDog); +} + +void who_cmd (struct parameters & a) +{ + int i = I_Am (); + if (I_Am() == a.target_unit) + com->printf ("who%c\r\n", a.target_unit); +} + +struct kb_command { + const char * cmd_word; // points to text e.g. "menu" + const char * explan; + void (*f)(struct parameters &); // points to function +} ; + +struct kb_command const command_list[] = { + {"ls", "Lists available commands", menucmd}, + {"?", "Lists available commands, same as ls", menucmd}, + {"fw", "forward", fw_cmd}, + {"re", "reverse", re_cmd}, + {"rb", "regen brake 0 to 99 %", rb_cmd}, + {"hb", "hand brake", hb_cmd}, + {"v", "set motors V percent RANGE 0 to 100", v_cmd}, + {"i", "set motors I percent RANGE 0 to 100", i_cmd}, + {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd}, + {"who", "search for connected units, e.g. 3who returs 'Hi there' if found", who_cmd}, + {"mode", "read or set params in eeprom", mode_cmd}, + {"erase", "set eeprom contents to all 0xff", erase_cmd}, + {"tem", "report temperature", temperature_cmd}, + {"kd", "kick the dog, reloads WatchDog", kd_cmd}, + {"rpm", "read motor pair speeds", rpm_cmd}, + {"rvi", "read most recent values sent to pwms", rvi_cmd}, + {"rdi", "read motor currents and power voltage", rdi_cmd}, + {"bc", "bogie constants - wheel dia, motor pinion, wheel gear", bogie_constants_report_cmd}, + {"nu", "do nothing", null_cmd}, +}; + +const int numof_menu_items = sizeof(command_list) / sizeof(kb_command); +void menucmd (struct parameters & a) +{ + if (a.respond) { + com->printf("\r\n\nDouble Brushless Motor Driver 2018\r\nAt menucmd function - listing commands:-\r\n"); + for(int i = 0; i < numof_menu_items; i++) + com->printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan); + com->printf("End of List of Commands\r\n"); + } +} + +/* +New - March 2018 +Using opto isolated serial port, paralleled up using same pair to multiple boards running this code. +New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to. +Commands without prefix digit - broadcast to all units, all to obey but none to respond. +Only units recognising its address from prefix digit may respond. This avoids bus contention. +But for BROADCAST commands, '0' may respond on behalf of the group +*/ +//void command_line_interpreter (void const *argument) +void command_line_interpreter () +{ + const int MAX_CMD_LEN = 120; + static char cmd_line[MAX_CMD_LEN + 4]; + static int cl_index = 0; + int ch, IAm = I_Am(); + char * pEnd, * cmd_line_ptr; + static struct parameters param_block ; + com = &com2; + while (com->readable()) { +// ch = tolower(com->getc()); + ch = com->getc(); + if (cl_index > MAX_CMD_LEN) { // trap out stupidly long command lines + com->printf ("Error!! Stupidly long cmd line\r\n"); + cl_index = 0; + } + if(ch != '\r') // was this the 'Enter' key? + cmd_line[cl_index++] = ch; // added char to command being assembled + else { // key was CR, may or may not be command to lookup + param_block.target_unit = BROADCAST; // Set to BROADCAST default once found command line '\r' + cmd_line_ptr = cmd_line; + cmd_line[cl_index] = 0; // null terminate command string + if(cl_index) { // If have got some chars to lookup + int i, wrdlen; + if (isdigit(cmd_line[0])) { // Look for command with prefix digit + cmd_line_ptr++; // point past identified digit prefix + param_block.target_unit = cmd_line[0]; // '0' to '9' + //com->printf ("Got prefix %c\r\n", cmd_line[0]); + } + for (i = 0; i < numof_menu_items; i++) { // Look for input match in command list + wrdlen = strlen(command_list[i].cmd_word); + if(strncmp(command_list[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(cmd_line_ptr[wrdlen])) { // If match found + for (int k = 0; k < MAX_PARAMS; k++) { + param_block.dbl[k] = 0.0; + } + param_block.position_in_list = i; +// param_block.last_time = clock (); + param_block.numof_dbls = 0; + pEnd = cmd_line_ptr + wrdlen; + while (*pEnd) { // Assemble all numerics as doubles + param_block.dbl[param_block.numof_dbls++] = strtod (pEnd, &pEnd); + while (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd) { + pEnd++; + } + } + //com->printf ("\r\n"); // Not allowed as many may output this. + //for (int k = 0; k < param_block.numof_dbls; k++) + // com->printf ("Read %.3f\r\n", param_block.dbl[k]); +// param_block.times[i] = clock(); + param_block.respond = false; + if (((param_block.target_unit == BROADCAST) && (IAm == '0')) || (IAm == param_block.target_unit)) + param_block.respond = true; // sorted 26/4/18 + // All boards to obey BROADCAST command, only specific board to obey number prefixed command + if ((param_block.target_unit == BROADCAST) || (IAm == param_block.target_unit)) + command_list[i].f(param_block); // execute command if addressed to this unit + i = numof_menu_items + 1; // to exit for loop + } // end of match found + } // End of for numof_menu_items + if(i == numof_menu_items) + com->printf("No Match Found for CMD [%s]\r\n", cmd_line); + } // End of If have got some chars to lookup + //com->printf("\r\n>"); + cl_index = 0; + } // End of else key was CR, may or may not be command to lookup + } // End of while (com->readable()) +// Thread::wait(20); // Using RTOS on this project +// } +} + +
--- a/cli_nortos.cpp Tue May 29 16:36:34 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -// DualBLS2018_03 -#include "mbed.h" -#include "BufferedSerial.h" - -#include <cctype> -#include "DualBLS.h" -using namespace std; - -extern int I_Am () ; // Returns boards id number as ASCII char '0', '1' etc. Code for Broadcast = '\r' -extern int WatchDog; - -const int BROADCAST = '\r'; -const int MAX_PARAMS = 20; -struct parameters { - int32_t position_in_list, // set but not used Apr 2018, contains i for i'th menu item -// last_time, // gets reading from clock() ; not known to be useful or reliable - numof_dbls, - target_unit; - double dbl[MAX_PARAMS]; - bool respond; -} ; - -// WithOUT RTOS -extern BufferedSerial com2, pc; -extern void send_test () ; -extern void setVI (double v, double i) ; -extern void setV (double v) ; -extern void setI (double i) ; -extern void read_last_VI (double * val) ; // only for test from cli - -BufferedSerial * com; - -void null_cmd (struct parameters & a) -{ - if (a.respond) - com->printf ("At null_cmd, board ID %c, parameters : First %.3f, second %.3f\r\n", I_Am(), a.dbl[0], a.dbl[1]); -} - -extern void mode_set (int mode, double val) ; -extern void read_supply_vi (double * val) ; - -void rdi_cmd (struct parameters & a) // read motor currents -{ - if (a.respond) { - double r[4]; - read_supply_vi (r); // get MotorA.I.ave, MotorB.I.ave, Battery volts - com->printf ("rdi%.0f %.0f %.1f\r", r[0], r[1], r[2]); // Format good to be unpicked by cli in touch screen controller - } -} - -void rvi_cmd (struct parameters & a) // read last normalised values sent to pwms -{ - if (a.respond) { - double r[6]; - read_last_VI (r); - com->printf ("rvi%.2f %.2f %.2f %.2f\r", r[0], r[1], r[2], r[3]); - } -} - -void fw_cmd (struct parameters & a) // Forward command -{ - mode_set (FORWARD, 0.0); -} - -void re_cmd (struct parameters & a) // Reverse command -{ - mode_set (REVERSE, 0.0); -} - -void rb_cmd (struct parameters & a) // Regen brake command -{ - double b = a.dbl[0] / 100.0; -// com->printf ("Applying brake %.3f\r\n", b); - mode_set (REGENBRAKE, b); -// apply_brake (b); -} - -extern bool wr_24LC64 (int mem_start_addr, char * source, int length) ; -extern bool rd_24LC64 (int mem_start_addr, char * dest, int length) ; - -void erase_cmd (struct parameters & a) // Sets eeprom contents to all 0xff. 256 pages of 32 bytes to do -{ - char t[36]; - for (int i = 0; i < 32; i++) - t[i] = 0xff; - for (int i = 0; i < 8191; i += 32) { - com->printf ("."); - if (!wr_24LC64 (i, t, 32)) - com->printf ("eeprom write prob\r\n"); - } -} -/*struct motorpairoptions { // This to be user settable in eeprom, 32 bytes - uint8_t MotA_dir, // 0 or 1 - MotB_dir, // 0 or 1 - gang, // 0 for separate control (robot mode), 1 for ganged loco bogie mode - serv1, // 0, 1, 2 = Not used, Input, Output - serv2, // 0, 1, 2 = Not used, Input, Output - cmd_source, // 0 Invalid, 1 COM1, 2 COM2, 3 Pot, 4 Servo1, 5 Servo2 - last; -} ; -*/ - -void mode_cmd (struct parameters & a) // With no params, reads eeprom contents. With params sets eeprom contents -{ - if (a.target_unit == BROADCAST) { -// com->printf ("At mode_cmd, can not use BROADCAST with mode_cmd\r\n"); - } else { - char t[36]; - com->printf ("At mode_cmd with node %d\r\n", a.target_unit); - rd_24LC64 (0, t, 32); - com->printf ("Numof params=%d\r\n", a.numof_dbls); - for (int i = 0; i < numofopts; i++) - com->printf ("%2x\t%s\r\n", t[i], option_list[i].t); - if (a.numof_dbls == 0) { // Read present contents, do not write - com->printf ("That's it\r\n"); - } else { // Write new shit to eeprom - com->printf ("\r\n"); - if (a.numof_dbls != numofopts) { - com->printf ("params required = %d, you offered %d\r\n", numofopts, a.numof_dbls); - } else { // Have been passed correct number of parameters - int b; - com->printf("Ready to write params to eeprom\r\n"); - for (int i = 0; i < numofopts; i++) { - b = (int)a.dbl[i]; // parameter value to check against limits - if (i == 6) // Alternative ID must be turned to ascii - b |= '0'; - if ((b < option_list[i].min) || (b > option_list[i].max)) { // if parameter out of range - com->printf("Warning - Parameter = %d, out of range, setting to default %d\r\n", b, option_list[i].def); - b = option_list[i].def; - } - com->printf ("0x%2x\t%s\r\n", (t[i] = b), option_list[i].t); - } - wr_24LC64 (0, t, numofopts); - com->printf("Parameters set in eeprom\r\n"); - } - } - } -} -/*void coast_cmd (struct parameters & a) { // Coast - -} -*/ -void hb_cmd (struct parameters & a) -{ - if (a.respond) { - com->printf ("numof params = %d\r\n", a.numof_dbls); - com->printf ("Hand Brake : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]); - } - mode_set (HANDBRAKE, 0.0); -} - -extern void read_RPM (uint32_t * dest) ; -void rpm_cmd (struct parameters & a) // to report e.g. RPM 1000 1000 ; speed for both motors -{ - if (a.respond) { - uint32_t dest[3]; - read_RPM (dest); - com->printf ("rpm%d %d\r", dest[0], dest[1]); - } -} - -void menucmd (struct parameters & a); - -void vi_cmd (struct parameters & a) -{ -// if (a.respond) -// com->printf ("In setVI, setting V to %.2f, I %.2f\r\n", a.dbl[0], a.dbl[1]); - setVI (a.dbl[0] / 100.0, a.dbl[1] / 100.0); -} - -void v_cmd (struct parameters & a) -{ -// if (a.respond) -// com->printf ("In setV, setting V to %.2f\r\n", a.dbl[0]); - setV (a.dbl[0] / 100.0); -} - -void i_cmd (struct parameters & a) -{ -// if (a.respond) -// com->printf ("In setI, setting I to %.2f\r\n", a.dbl[0]); - setI (a.dbl[0] / 100.0); -} - -void kd_cmd (struct parameters & a) // kick the watchdog -{ - WatchDog = WATCHDOG_RELOAD + (I_Am() & 0x0f); -// com->printf ("Poked %d up Dog\r\n", WatchDog); -} - -void who_cmd (struct parameters & a) -{ - int i = I_Am (); - if (I_Am() == a.target_unit) - com->printf ("Hi there, I am %c\r\n", a.target_unit); -} - -struct kb_command { - const char * cmd_word; // points to text e.g. "menu" - const char * explan; - void (*f)(struct parameters &); // points to function -} ; - -struct kb_command const command_list[] = { - {"ls", "Lists available commands", menucmd}, - {"?", "Lists available commands, same as ls", menucmd}, - {"fw", "forward", fw_cmd}, - {"re", "reverse", re_cmd}, - {"rb", "regen brake 0 to 99 %", rb_cmd}, - {"hb", "hand brake", hb_cmd}, - {"v", "set motors V percent RANGE 0 to 100", v_cmd}, - {"i", "set motors I percent RANGE 0 to 100", i_cmd}, - {"vi", "set motors V and I percent RANGE 0 to 100", vi_cmd}, - {"who", "search for connected units, e.g. 3who returs 'Hi there' if found", who_cmd}, - {"mode", "read or set params in eeprom", mode_cmd}, - {"erase", "set eeprom contents to all 0xff", erase_cmd}, - {"kd", "kick the dog, reloads WatchDog", kd_cmd}, - {"rpm", "read motor pair speeds", rpm_cmd}, - {"rvi", "read most recent values sent to pwms", rvi_cmd}, - {"rdi", "read motor currents and power voltage", rdi_cmd}, - {"nu", "do nothing", null_cmd}, -}; - -const int numof_menu_items = sizeof(command_list) / sizeof(kb_command); -void menucmd (struct parameters & a) -{ - if (a.respond) { - com->printf("\r\n\nDouble Brushless Motor Driver 2018\r\nAt menucmd function - listing commands:-\r\n"); - for(int i = 0; i < numof_menu_items; i++) - com->printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan); - com->printf("End of List of Commands\r\n"); - } -} - -/* -New - March 2018 -Using opto isolated serial port, paralleled up using same pair to multiple boards running this code. -New feature - commands have optional prefix digit 0-9 indicating which unit message is addressed to. -Commands without prefix digit - broadcast to all units, all to obey but none to respond. -Only units recognising its address from prefix digit may respond. This avoids bus contention. -But for BROADCAST commands, '0' may respond on behalf of the group -*/ -//void command_line_interpreter (void const *argument) -void command_line_interpreter () -{ - const int MAX_CMD_LEN = 120; - static char cmd_line[MAX_CMD_LEN + 4]; - static int cl_index = 0; - int ch, IAm = I_Am(); - char * pEnd, * cmd_line_ptr; - static struct parameters param_block ; - com = &com2; - while (com->readable()) { -// ch = tolower(com->getc()); - ch = com->getc(); - if (cl_index > MAX_CMD_LEN) { // trap out stupidly long command lines - com->printf ("Error!! Stupidly long cmd line\r\n"); - cl_index = 0; - } - if(ch != '\r') // was this the 'Enter' key? - cmd_line[cl_index++] = ch; // added char to command being assembled - else { // key was CR, may or may not be command to lookup - param_block.target_unit = BROADCAST; // Set to BROADCAST default once found command line '\r' - cmd_line_ptr = cmd_line; - cmd_line[cl_index] = 0; // null terminate command string - if(cl_index) { // If have got some chars to lookup - int i, wrdlen; - if (isdigit(cmd_line[0])) { // Look for command with prefix digit - cmd_line_ptr++; // point past identified digit prefix - param_block.target_unit = cmd_line[0]; // '0' to '9' - //com->printf ("Got prefix %c\r\n", cmd_line[0]); - } - for (i = 0; i < numof_menu_items; i++) { // Look for input match in command list - wrdlen = strlen(command_list[i].cmd_word); - if(strncmp(command_list[i].cmd_word, cmd_line_ptr, wrdlen) == 0 && !isalpha(cmd_line_ptr[wrdlen])) { // If match found - for (int k = 0; k < MAX_PARAMS; k++) { - param_block.dbl[k] = 0.0; - } - param_block.position_in_list = i; -// param_block.last_time = clock (); - param_block.numof_dbls = 0; - pEnd = cmd_line_ptr + wrdlen; - while (*pEnd) { // Assemble all numerics as doubles - param_block.dbl[param_block.numof_dbls++] = strtod (pEnd, &pEnd); - while (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd) { - pEnd++; - } - } - //com->printf ("\r\n"); // Not allowed as many may output this. - //for (int k = 0; k < param_block.numof_dbls; k++) - // com->printf ("Read %.3f\r\n", param_block.dbl[k]); -// param_block.times[i] = clock(); - param_block.respond = false; - if (((param_block.target_unit == BROADCAST) && (IAm == '0')) || (IAm == param_block.target_unit)) - param_block.respond = true; // sorted 26/4/18 - // All boards to obey BROADCAST command, only specific board to obey number prefixed command - if ((param_block.target_unit == BROADCAST) || (IAm == param_block.target_unit)) - command_list[i].f(param_block); // execute command if addressed to this unit - i = numof_menu_items + 1; // to exit for loop - } // end of match found - } // End of for numof_menu_items - if(i == numof_menu_items) - com->printf("No Match Found for CMD [%s]\r\n", cmd_line); - } // End of If have got some chars to lookup - //com->printf("\r\n>"); - cl_index = 0; - } // End of else key was CR, may or may not be command to lookup - } // End of while (com->readable()) -// Thread::wait(20); // Using RTOS on this project -// } -} - -
--- a/main.cpp Tue May 29 16:36:34 2018 +0000 +++ b/main.cpp Tue Jun 05 07:19:39 2018 +0000 @@ -6,12 +6,12 @@ /* New 29th May 2018 - YET TO CODE FOR - Fwd/Rev line from possible remote hand control box has signal routed to T5 - Also new LMT01 temperature sensor routed to T1 + Also new LMT01 temperature sensor routed to T1 - and rerouted to PC_13 at InterruptIn on T1 (ports A and B I think) not workable */ /* STM32F401RE - compile using NUCLEO-F401RE -// PROJECT - Dual Brushless Motor Controller - Jon Freeman April 2018. +// PROJECT - Dual Brushless Motor Controller - Jon Freeman June 2018. AnalogIn to read each motor current @@ -28,6 +28,8 @@ */ +//#if defined (TARGET_NUCLEO_F446ZE) +#if defined (TARGET_NUCLEO_F401RE) // Hoped to select servo functions from user info stored on EEROM. Too difficult. Do not define servo as in and out @@ -80,7 +82,11 @@ PortOut MotB (PortB, PORT_B_MASK); // Pin 1 VBAT NET +3V3 -DigitalIn J3 (PC_13, PullUp);// Pin 2 Jumper pulls to GND, R floats Hi + +//DigitalIn J3 (PC_13, PullUp);// Pin 2 Jumper pulls to GND, R floats Hi +InterruptIn Temperature_pin (PC_13);// Pin 2 June 2018 - taken for temperature sensor - hard wired to T1 due to wrong thought T1 could be InterruptIn + + // Pin 3 PC14-OSC32_IN NET O32I // Pin 4 PC15-OSC32_OUT NET O32O // Pin 5 PH0-OSC_IN NET PH1 @@ -132,7 +138,15 @@ //BufferedSerial extra_ser (PA_11, PA_12); // Pins 44, 45 tx, rx to XBee module DigitalOut T2 (PA_11); // Pin 44 // was DigitalOut T1 (PA_12); // Pin 45 -InterruptIn T1 (PA_12); // Pin 45 now input counting pulses from LMT01 temperature sensor + + +//InterruptIn T1 (PA_12); // Pin 45 now input counting pulses from LMT01 temperature sensor +// InterruptIn DOES NOT WORK ON PA_12. Boards are being made, will have to wire link PA12 to PC13 +DigitalIn T1 (PA_12); +////InterruptIn T1 (PC_13); // Pin 45 now input counting pulses from LMT01 temperature sensor + + + // Pin 46 SWDIO // Pin 47 VSS // Pin 48 VDD @@ -160,7 +174,9 @@ // Pin 64 VDD // SYSTEM CONSTANTS - +#endif +#if defined (TARGET_NUCLEO_F446ZE) +#endif /* Global variable declarations */ volatile uint32_t fast_sys_timer = 0; // gets incremented by our Ticker ISR every VOLTAGE_READ_INTERVAL_US int WatchDog = WATCHDOG_RELOAD + 80; // Allow extra few seconds at powerup @@ -171,13 +187,31 @@ int IAm; bool loop_flag = false; // made true in ISR_loop_timer, picked up and made false again in main programme loop bool flag_8Hz = false; // As loop_flag but repeats 8 times per sec +bool temp_sensor_exists = false; +char mode_bytes[36]; +uint32_t temp_sensor_count = 0, // incremented by every rising edge from LMT01 + last_temp_count = 0; // global updated approx every 100ms after each LMT01 conversion completes +// struct single_bogie_options bogie; /* End of Global variable declarations */ Ticker tick_vread; // Device to cause periodic interrupts, used to time voltage readings etc Ticker loop_timer; // Device to cause periodic interrupts, used to sync iterations of main programme loop +Ticker temperature_find_ticker; +Timer temperature_timer; // Interrupt Service Routines +void ISR_temperature_find_ticker () { // every 960 us, i.e. slightly faster than once per milli sec + static bool readflag = false; + int t = temperature_timer.read_ms (); + if ((t == 5) && (!readflag)) { + last_temp_count = temp_sensor_count; + temp_sensor_count = 0; + readflag = true; + } + if (t == 6) + readflag = false; +} /** void ISR_loop_timer () * This ISR responds to Ticker interrupts at a rate of (probably) 32 times per second (check from constant declarations above) @@ -240,7 +274,7 @@ return rx_active; } -void RControl_In::rise () +void RControl_In::rise () // These may not work as use of PortB as port may bugger InterruptIn use { t.stop (); period_us = t.read_us (); @@ -505,11 +539,14 @@ Hindex[1] = Hindex[0]; } - uint32_t temp_sensor_count = 0; // global - bool temp_count_in_progress = false; -void temp_sensor_isr () { // got rising edge from LMT01 +void temp_sensor_isr () { // got rising edge from LMT01. ALMOST CERTAIN this misses some + int t = temperature_timer.read_us (); // Must be being overrun by something, most likely culprit A-D reading ? + temperature_timer.reset (); temp_sensor_count++; + if (t > 18) // Yes proved some interrupts get missed, this fixes temperature reading + temp_sensor_count++; +// T2 = !T2; // scope hanger } void MAH_isr () @@ -576,29 +613,6 @@ d[3] = MotorB.last_I; } -/*void sincostest () { - sinv = sin(angle); // to set speed and direction of MotorA - cosv = cos(angle); // to set speed and direction of MotorB - Servos[0]->write ((sinv + 1.0) / 2.0); - Servos[1]->write ((cosv + 1.0) / 2.0); - angle += angle_step; - if (angle > TWOPI) - angle -= TWOPI; - if (sinv > 0.0) - MotorA.set_mode (FORWARD); - else { - MotorA.set_mode (REVERSE); - sinv = -sinv; - } - MotorA.set_V_limit (0.01 + (sinv / 1.3)); - if (cosv > 0.0) - MotorB.set_mode (FORWARD); - else { - MotorB.set_mode (REVERSE); - cosv = -cosv; - } - MotorB.set_V_limit (0.01 + (cosv / 1.3)); -}*/ /** void AtoD_reader () // Call to here every VOLTAGE_READ_INTERVAL_US = 50 once loop responds to flag set in isr @@ -606,17 +620,8 @@ */ void AtoD_reader () // Call to here every VOLTAGE_READ_INTERVAL_US = 50 once loop responds to flag set in isr { - static uint32_t i = 0, tab_ptr = 0, local_temperature_count = 0; + static uint32_t i = 0, tab_ptr = 0; -// sincostest (); -// uint32_t temp_sensor_count = 0; // global -// bool temp_count_in_progress = false; - if (local_temperature_count == temp_sensor_count) - temp_count_in_progress = false; - else { - temp_count_in_progress = true; - local_temperature_count = temp_sensor_count; - } if (MotorA.tickleon) MotorA.high_side_off (); if (MotorB.tickleon) @@ -711,10 +716,6 @@ } ; */ int I_Am () { // Returns boards id number as ASCII char -// int i = J3; -// if (i != 0) -// i = 1; -// return i | '0'; return IAm; } @@ -728,7 +729,8 @@ MotPtr[0] = &MotorA; // Pointers to motor class objects MotPtr[1] = &MotorB; - T1.rise (&temp_sensor_isr); + Temperature_pin.fall (&temp_sensor_isr); + Temperature_pin.mode (PullUp); MAH1.rise (& MAH_isr); // Set up interrupt vectors MAH1.fall (& MAH_isr); @@ -756,14 +758,16 @@ // Setup system timers to cause periodic interrupts to synchronise and automate volt and current readings, loop repeat rate etc tick_vread.attach_us (&ISR_voltage_reader, VOLTAGE_READ_INTERVAL_US); // Start periodic interrupt generator loop_timer.attach_us (&ISR_loop_timer, MAIN_LOOP_REPEAT_TIME_US); // Start periodic interrupt generator + temperature_find_ticker.attach_us (&ISR_temperature_find_ticker, 960); // Done setting up system interrupt timers + temperature_timer.start (); - const int TXTBUFSIZ = 36; - char buff[TXTBUFSIZ]; +// const int TXTBUFSIZ = 36; +// char buff[TXTBUFSIZ]; pc.baud (9600); com3.baud (1200); com2.baud (19200); - + if (check_24LC64() != 0xa0) { // searches for i2c devices, returns address of highest found pc.printf ("Check for 24LC64 eeprom FAILED\r\n"); com2.printf ("Check for 24LC64 eeprom FAILED\r\n"); @@ -777,15 +781,15 @@ // k = rd_24LC64 (0x1240, buff, strlen(ramtst)); // pc.printf("Ram test returned [%s], wr ret'd [%s], rd ret'd [%s]\r\n", buff, j ? "true" : "false", k ? "true" : "false"); // com2.printf("Ram test returned [%s], wr ret'd [%s], rd ret'd [%s]\r\n", buff, j ? "true" : "false", k ? "true" : "false"); - k = rd_24LC64 (0, buff, 32); + k = rd_24LC64 (0, mode_bytes, 32); // if (k) // com2.printf ("Good read from eeprom\r\n"); if (!k) com2.printf ("Error reading from eeprom\r\n"); int err = 0; - for (int i = 0; i < numofopts; i++) { - if ((buff[i] < option_list[i].min) || (buff[i] > option_list[i].max)) { + for (int i = 0; i < numof_eeprom_options; i++) { + if ((mode_bytes[i] < option_list[i].min) || (mode_bytes[i] > option_list[i].max)) { com2.printf ("EEROM error with %s\r\n", option_list[i].t); err++; } @@ -794,14 +798,14 @@ } IAm = '0'; if (err == 0) { - MotorA.direction_set (buff[0]); - MotorB.direction_set (buff[1]); - IAm = buff[6]; + MotorA.direction_set (mode_bytes[MOTADIR]); + MotorB.direction_set (mode_bytes[MOTBDIR]); + IAm = mode_bytes[ID]; } // Alternative ID 1 to 9 // com2.printf ("Alternative ID = 0x%2x\r\n", buff[6]); } -// T1 = 0; Now interruptIn counting pulses from LMT01 temperature sensor +// T1 = 0; Now WRONGLY hoped to be InterruptIn counting pulses from LMT01 temperature sensor T2 = 0; // T2, T3, T4 As yet unused pins T3 = 0; T4 = 0; @@ -821,6 +825,10 @@ Servos[0] = & Servo1; Servo Servo2 (PB_9) ; Servos[1] = & Servo2; + + pc.printf ("last_temp_count = %d\r\n", last_temp_count); // Has had time to do at least 1 conversion + if ((last_temp_count > 160) && (last_temp_count < 2400)) // in range -40 to +100 degree C + temp_sensor_exists = true; /* // Setup Complete ! Can now start main control forever loop. // March 16th 2018 thoughts !!! @@ -843,6 +851,7 @@ break; } */ + pc.printf ("Ready to go!, wheel gear in position %d\r\n", WHEELGEAR); while (1) { // Loop forever, repeats synchroised by waiting for ticker Interrupt Service Routine to set 'loop_flag' true while (!loop_flag) { // Most of the time is spent in this loop, repeatedly re-checking for commands from pc port command_line_interpreter () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true @@ -866,8 +875,14 @@ eighth_sec_count++; if (eighth_sec_count > 6) { // Send some status info out of serial port every second and a bit or thereabouts eighth_sec_count = 0; - MotorA.current_calc (); // Updates readings in MotorA.I.min, MotorA.I.ave and MotorA.I.max - MotorB.current_calc (); + MotorA.current_calc (); // Updates readings in MotorA.I.min, MotorA.I.ave and MotorA.I.max + MotorB.current_calc (); + if (temp_sensor_exists) { + double tmprt = (double) last_temp_count; + tmprt /= 16.0; + tmprt -= 50.0; + pc.printf ("Temp %.2f\r\n", tmprt); + } // com2.printf ("V=%+.2f, Pot=%+.2f, HA %d, HB %d, IAmin %d, IAave %d, IAmax %d, IB %d, Arpm %d, Brpm %d\r\n", Read_BatteryVolts(), Read_DriverPot(), MotorA.read_Halls (), MotorB.read_Halls (), MotorA.I.min, MotorA.I.ave, MotorA.I.max, MotorB.I.ave, (Apps * 60) / 24, (Bpps * 60) / 24); } } // End of if(flag_8Hz)