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

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?

UserRevisionLine numberNew contents of line
JonFreeman 14:acaa1add097b 1 /*
JonFreeman 14:acaa1add097b 2 STM3_ESC Electronic Speed Controller board, drives Two Brushless Motors, full Four Quadrant Control.
JonFreeman 14:acaa1add097b 3 Jon Freeman B. Eng Hons
JonFreeman 16:d1e4b9ad3b8b 4 2015 - 2020
JonFreeman 14:acaa1add097b 5 */
JonFreeman 11:bfb73f083009 6 #include "mbed.h"
JonFreeman 11:bfb73f083009 7
JonFreeman 11:bfb73f083009 8 #ifndef MBED_DUALBLS_H
JonFreeman 11:bfb73f083009 9 #define MBED_DUALBLS_H
JonFreeman 11:bfb73f083009 10
JonFreeman 16:d1e4b9ad3b8b 11 //#define USING_DC_MOTORS // NO LONGER SUPPORTED Uncomment this to play with Dinosaur DC motors - WARNING deprecated feature
JonFreeman 3:ecb00e0e8d68 12
JonFreeman 14:acaa1add097b 13 //#define TEMP_SENSOR_ENABLE // - WARNING deprecated feature, sensor chosen imposed heavy burden on cpu, future looks to simpler analogue type
JonFreeman 13:ef7a06fa11de 14
JonFreeman 12:d1d21a2941ef 15 #include "BufferedSerial.h"
JonFreeman 16:d1e4b9ad3b8b 16 const uint32_t MOTOR_HANDBRAKE = 0,
JonFreeman 16:d1e4b9ad3b8b 17 MOTOR_FORWARD = 8,
JonFreeman 16:d1e4b9ad3b8b 18 MOTOR_REVERSE = 16,
JonFreeman 16:d1e4b9ad3b8b 19 MOTOR_REGENBRAKE = 24;
JonFreeman 12:d1d21a2941ef 20
JonFreeman 16:d1e4b9ad3b8b 21 const uint32_t TIMEOUT_SECONDS = 2,
JonFreeman 5:ca86a7848d54 22
JonFreeman 5:ca86a7848d54 23 /* Please Do Not Alter these */
JonFreeman 16:d1e4b9ad3b8b 24 PWM_PRESECALER_DEFAULT = 2,
JonFreeman 8:93203f473f6e 25 VOLTAGE_READ_INTERVAL_US = 50, // Interrupts timed every 50 micro sec, runs around loop performing 1 A-D conversion per pass
JonFreeman 5:ca86a7848d54 26 MAIN_LOOP_REPEAT_TIME_US = 31250, // 31250 us, with TACHO_TAB_SIZE = 32 means tacho_ticks_per_time is tacho_ticks_per_second
JonFreeman 5:ca86a7848d54 27 MAIN_LOOP_ITERATION_Hz = 1000000 / MAIN_LOOP_REPEAT_TIME_US,
JonFreeman 8:93203f473f6e 28 PWM_HZ = 15000, // chosen to be above cutoff frequency of average human ear
JonFreeman 12:d1d21a2941ef 29 // PWM_HZ = 8000, // chosen to be above cutoff frequency of average human ear - clearly audible annoying noise
JonFreeman 8:93203f473f6e 30 MAX_PWM_TICKS = (SystemCoreClock / (PWM_HZ * PWM_PRESECALER_DEFAULT)),
JonFreeman 16:d1e4b9ad3b8b 31 // TICKLE_TIMES = 100 ,
JonFreeman 16:d1e4b9ad3b8b 32 TICKLE_TIMES = 10 , // Massively reduced May 2020 in connection with handbrake implementation.
JonFreeman 5:ca86a7848d54 33 WATCHDOG_RELOAD = (TIMEOUT_SECONDS * 8); // WatchDog counter ticked down in 8Hz loop
JonFreeman 5:ca86a7848d54 34
JonFreeman 3:ecb00e0e8d68 35 const double PI = 4.0 * atan(1.0),
JonFreeman 3:ecb00e0e8d68 36 TWOPI = 8.0 * atan(1.0);
JonFreeman 16:d1e4b9ad3b8b 37 /* End of Please Do Not Alter these */
JonFreeman 5:ca86a7848d54 38
JonFreeman 16:d1e4b9ad3b8b 39 enum {COM_SOURCES, COM1, COM2, HAND, RC_IN1, RC_IN2, RC_IN_BOTH, THEEND} ; // RC_IN_BOTH new Dec 2019
JonFreeman 11:bfb73f083009 40
JonFreeman 16:d1e4b9ad3b8b 41 // List user settable firmware bytes in EEROM
JonFreeman 16:d1e4b9ad3b8b 42 enum {MOTADIR, MOTBDIR, MOTAPOLES, MOTBPOLES, ISHUNTA, ISHUNTB, POT_REGBRAKE_RANGE, SVO1, SVO2, RCIN1, RCIN2,
JonFreeman 12:d1d21a2941ef 43 COMM_SRC, BOARD_ID, TOP_SPEED, WHEELDIA, MOTPIN, WHEELGEAR,
JonFreeman 16:d1e4b9ad3b8b 44 RCI1_TRIM, RCI2_TRIM, RCIN_REGBRAKE_RANGE, RCIN_STICK_ATTACK, // RC in trims new Dec 2019
JonFreeman 16:d1e4b9ad3b8b 45 RCIN1REVERSE, RCIN2REVERSE, NOM_SYSTEM_VOLTS, BRAKE_EFFECTIVENESS, BAUD, FUT11,
JonFreeman 16:d1e4b9ad3b8b 46 FUT12, FUT13, FUT14, FUT16,} ; // These represent byte address offsets in 24LC64 rom user settable firmware settings
JonFreeman 5:ca86a7848d54 47
JonFreeman 16:d1e4b9ad3b8b 48 enum { // List of fault numbers currently dealt with by error handler
JonFreeman 12:d1d21a2941ef 49 FAULT_0,
JonFreeman 12:d1d21a2941ef 50 FAULT_EEPROM,
JonFreeman 12:d1d21a2941ef 51 FAULT_BOARD_ID,
JonFreeman 12:d1d21a2941ef 52 FAULT_COM_LINE_LEN,
JonFreeman 12:d1d21a2941ef 53 FAULT_COM_LINE_NOMATCH,
JonFreeman 12:d1d21a2941ef 54 FAULT_COM_LINE_LEN_PC,
JonFreeman 12:d1d21a2941ef 55 FAULT_COM_LINE_LEN_TS,
JonFreeman 12:d1d21a2941ef 56 FAULT_COM_LINE_NOMATCH_PC,
JonFreeman 12:d1d21a2941ef 57 FAULT_COM_LINE_NOMATCH_TS,
JonFreeman 12:d1d21a2941ef 58 FAULT_UNRECOGNISED_STATE,
JonFreeman 12:d1d21a2941ef 59 FAULT_MAX,
JonFreeman 12:d1d21a2941ef 60 NUMOF_REPORTABLE_TS_ERRORS
JonFreeman 14:acaa1add097b 61 } ; // List of fault numbers currently dealt with by error handler
JonFreeman 12:d1d21a2941ef 62
JonFreeman 12:d1d21a2941ef 63 class error_handling_Jan_2019
JonFreeman 12:d1d21a2941ef 64 {
JonFreeman 12:d1d21a2941ef 65 int32_t ESC_fault[NUMOF_REPORTABLE_TS_ERRORS] ; // Some number of reportable error codes, accessible through set and read members
JonFreeman 12:d1d21a2941ef 66 public:
JonFreeman 12:d1d21a2941ef 67 error_handling_Jan_2019 () { // default constructor
JonFreeman 12:d1d21a2941ef 68 for (int i = 0; i < (sizeof(ESC_fault) / sizeof(int32_t)); i++)
JonFreeman 12:d1d21a2941ef 69 ESC_fault[i] = 0;
JonFreeman 12:d1d21a2941ef 70 }
JonFreeman 12:d1d21a2941ef 71 void set (uint32_t, int32_t) ;
JonFreeman 12:d1d21a2941ef 72 void clr (uint32_t) ;
JonFreeman 12:d1d21a2941ef 73 uint32_t read (uint32_t) ;
JonFreeman 12:d1d21a2941ef 74 bool all_good () ;
JonFreeman 12:d1d21a2941ef 75 void report_any (bool) ; // retain ? true or false
JonFreeman 6:f289a49c1eae 76 } ;
JonFreeman 10:e40d8724268a 77
JonFreeman 12:d1d21a2941ef 78 enum {SOURCE_PC, SOURCE_TS} ;
JonFreeman 16:d1e4b9ad3b8b 79 const int BROADCAST = '\r';
JonFreeman 16:d1e4b9ad3b8b 80 const int MAX_CLI_PARAMS = 12;
JonFreeman 12:d1d21a2941ef 81 const int MAX_CMD_LEN = 220;
JonFreeman 12:d1d21a2941ef 82
JonFreeman 14:acaa1add097b 83 struct parameters { // Used in serial comms with pc and other controller (e.g. touch-screen)
JonFreeman 12:d1d21a2941ef 84 struct kb_command const * command_list;
JonFreeman 12:d1d21a2941ef 85 BufferedSerial * com; // pc or com2
JonFreeman 12:d1d21a2941ef 86 int32_t position_in_list, numof_dbls, target_unit, source, numof_menu_items;
JonFreeman 16:d1e4b9ad3b8b 87 double dbl[MAX_CLI_PARAMS];
JonFreeman 12:d1d21a2941ef 88 bool respond, resp_always;
JonFreeman 12:d1d21a2941ef 89 } ;
JonFreeman 12:d1d21a2941ef 90
JonFreeman 16:d1e4b9ad3b8b 91 enum {ZONE_BRAKE, ZONE_COAST, ZONE_DRIVE} ;
JonFreeman 16:d1e4b9ad3b8b 92 class RC_stick_info { // info read concerning stick positions
JonFreeman 16:d1e4b9ad3b8b 93 public:
JonFreeman 16:d1e4b9ad3b8b 94 double raw, // range 0.0 to 1.0 after clipping and correction
JonFreeman 16:d1e4b9ad3b8b 95 deflection; // how far from centre or min positon
JonFreeman 16:d1e4b9ad3b8b 96 double brake_effort, // braking effort
JonFreeman 16:d1e4b9ad3b8b 97 drive_effort; // driving effort
JonFreeman 16:d1e4b9ad3b8b 98 uint32_t zone; // in drive, coast or braking zone (if drive, direction in 'stick_implied_motor_direction')
JonFreeman 16:d1e4b9ad3b8b 99 uint32_t chan_mode;
JonFreeman 16:d1e4b9ad3b8b 100 int32_t stick_implied_motor_direction; // -1, 0, +1 but could be in drive, coast or brake regions
JonFreeman 16:d1e4b9ad3b8b 101 bool active;
JonFreeman 16:d1e4b9ad3b8b 102 RC_stick_info () {
JonFreeman 16:d1e4b9ad3b8b 103 active = false;
JonFreeman 16:d1e4b9ad3b8b 104 chan_mode = 0;
JonFreeman 16:d1e4b9ad3b8b 105 zone = ZONE_COAST;
JonFreeman 16:d1e4b9ad3b8b 106 drive_effort = brake_effort = 0.0;
JonFreeman 16:d1e4b9ad3b8b 107 }
JonFreeman 16:d1e4b9ad3b8b 108 } ;
JonFreeman 16:d1e4b9ad3b8b 109
JonFreeman 14:acaa1add097b 110 class cli_2019 { // cli Command Line Interpreter, two off, 1 for pc comms, other touch-screen controller comms
JonFreeman 12:d1d21a2941ef 111 struct kb_command const * commandlist ;
JonFreeman 16:d1e4b9ad3b8b 112 uint32_t clindex;
JonFreeman 16:d1e4b9ad3b8b 113 char cmdline[MAX_CMD_LEN + 8];
JonFreeman 16:d1e4b9ad3b8b 114 char * cmdline_ptr;
JonFreeman 12:d1d21a2941ef 115 parameters a ;
JonFreeman 12:d1d21a2941ef 116 public:
JonFreeman 16:d1e4b9ad3b8b 117 cli_2019 (BufferedSerial * comport, kb_command const * list, uint32_t list_len, uint32_t source) {
JonFreeman 12:d1d21a2941ef 118 a.com = comport ;
JonFreeman 12:d1d21a2941ef 119 a.command_list = commandlist = list ;
JonFreeman 12:d1d21a2941ef 120 a.numof_menu_items = list_len ;
JonFreeman 12:d1d21a2941ef 121 a.source = source ;
JonFreeman 12:d1d21a2941ef 122 cmdline_ptr = cmdline;
JonFreeman 12:d1d21a2941ef 123 clindex = 0;
JonFreeman 12:d1d21a2941ef 124 if (source == SOURCE_PC)
JonFreeman 12:d1d21a2941ef 125 a.resp_always = true;
JonFreeman 12:d1d21a2941ef 126 else
JonFreeman 12:d1d21a2941ef 127 a.resp_always = false;
JonFreeman 12:d1d21a2941ef 128 } ;
JonFreeman 16:d1e4b9ad3b8b 129 void core () ;
JonFreeman 16:d1e4b9ad3b8b 130 void flush () ; // Used to clear startup transient garbage
JonFreeman 12:d1d21a2941ef 131 } ;
JonFreeman 12:d1d21a2941ef 132
JonFreeman 16:d1e4b9ad3b8b 133 const uint32_t MAX_I2C_DEVICES = 6;
JonFreeman 16:d1e4b9ad3b8b 134
JonFreeman 12:d1d21a2941ef 135 class eeprom_settings {
JonFreeman 12:d1d21a2941ef 136 I2C i2c;
JonFreeman 12:d1d21a2941ef 137 uint32_t errors;
JonFreeman 14:acaa1add097b 138 uint32_t i2c_device_count;
JonFreeman 16:d1e4b9ad3b8b 139 uint32_t i2c_device_list[MAX_I2C_DEVICES+1]; // max 12 i2c devices
JonFreeman 12:d1d21a2941ef 140 char settings [36];
JonFreeman 16:d1e4b9ad3b8b 141 double rpm2mphdbl, user_brake_rangedbl, Vnomdbl, brake_eff, top_speeddbl;
JonFreeman 16:d1e4b9ad3b8b 142 bool rd_24LC64 (uint32_t start_addr, char * dest, uint32_t length) ;
JonFreeman 16:d1e4b9ad3b8b 143 bool wr_24LC64 (uint32_t start_addr, char * dest, uint32_t length) ;
JonFreeman 12:d1d21a2941ef 144 bool set_24LC64_internal_address (int start_addr) ;
JonFreeman 12:d1d21a2941ef 145 bool ack_poll () ;
JonFreeman 16:d1e4b9ad3b8b 146 void update_dbls () ;
JonFreeman 12:d1d21a2941ef 147 public:
JonFreeman 12:d1d21a2941ef 148 eeprom_settings (PinName sda, PinName scl); // Constructor
JonFreeman 14:acaa1add097b 149 bool do_we_have_i2c (uint32_t x) ;
JonFreeman 12:d1d21a2941ef 150 char rd (uint32_t) ; // Read one setup char value from private buffer 'settings'
JonFreeman 12:d1d21a2941ef 151 bool wr (char, uint32_t) ; // Write one setup char value to private buffer 'settings'
JonFreeman 12:d1d21a2941ef 152 bool save () ; // Write 'settings' buffer to EEPROM
JonFreeman 12:d1d21a2941ef 153 bool set_defaults (); // Put default settings into EEPROM and local buffer
JonFreeman 12:d1d21a2941ef 154 uint32_t errs () ; // Return errors
JonFreeman 16:d1e4b9ad3b8b 155 const char * t (uint32_t);
JonFreeman 16:d1e4b9ad3b8b 156 uint32_t min (uint32_t) ;
JonFreeman 16:d1e4b9ad3b8b 157 uint32_t max (uint32_t) ;
JonFreeman 16:d1e4b9ad3b8b 158 uint32_t def (uint32_t) ;
JonFreeman 16:d1e4b9ad3b8b 159 bool in_range (char val, uint32_t p) ;
JonFreeman 16:d1e4b9ad3b8b 160 void edit (double * dbl, uint32_t numof_dbls) ;
JonFreeman 16:d1e4b9ad3b8b 161 double user_brake_range () ;
JonFreeman 16:d1e4b9ad3b8b 162 double brake_effectiveness () ;
JonFreeman 16:d1e4b9ad3b8b 163 double top_speed () ;
JonFreeman 16:d1e4b9ad3b8b 164 double Vnom () ;
JonFreeman 16:d1e4b9ad3b8b 165 double rpm2mph () ;
JonFreeman 16:d1e4b9ad3b8b 166 double rpm2mph (double) ;
JonFreeman 16:d1e4b9ad3b8b 167 uint32_t baud ();
JonFreeman 12:d1d21a2941ef 168 } ;
JonFreeman 12:d1d21a2941ef 169
JonFreeman 16:d1e4b9ad3b8b 170 struct optpar {
JonFreeman 16:d1e4b9ad3b8b 171 int32_t min, max, de_fault; // min, max, default
JonFreeman 16:d1e4b9ad3b8b 172 const char * txt; // description
JonFreeman 16:d1e4b9ad3b8b 173 } ;
JonFreeman 12:d1d21a2941ef 174
JonFreeman 11:bfb73f083009 175 #endif