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
STM3_ESC.h
- Committer:
- JonFreeman
- Date:
- 2020-06-09
- Revision:
- 16:d1e4b9ad3b8b
- Parent:
- 14:acaa1add097b
File content as of revision 16:d1e4b9ad3b8b:
/*
STM3_ESC Electronic Speed Controller board, drives Two Brushless Motors, full Four Quadrant Control.
Jon Freeman B. Eng Hons
2015 - 2020
*/
#include "mbed.h"
#ifndef MBED_DUALBLS_H
#define MBED_DUALBLS_H
//#define USING_DC_MOTORS // NO LONGER SUPPORTED Uncomment this to play with Dinosaur DC motors - WARNING deprecated feature
//#define TEMP_SENSOR_ENABLE // - WARNING deprecated feature, sensor chosen imposed heavy burden on cpu, future looks to simpler analogue type
#include "BufferedSerial.h"
const uint32_t MOTOR_HANDBRAKE = 0,
MOTOR_FORWARD = 8,
MOTOR_REVERSE = 16,
MOTOR_REGENBRAKE = 24;
const uint32_t TIMEOUT_SECONDS = 2,
/* Please Do Not Alter these */
PWM_PRESECALER_DEFAULT = 2,
VOLTAGE_READ_INTERVAL_US = 50, // Interrupts timed every 50 micro sec, runs around loop performing 1 A-D conversion per pass
MAIN_LOOP_REPEAT_TIME_US = 31250, // 31250 us, with TACHO_TAB_SIZE = 32 means tacho_ticks_per_time is tacho_ticks_per_second
MAIN_LOOP_ITERATION_Hz = 1000000 / MAIN_LOOP_REPEAT_TIME_US,
PWM_HZ = 15000, // chosen to be above cutoff frequency of average human ear
// PWM_HZ = 8000, // chosen to be above cutoff frequency of average human ear - clearly audible annoying noise
MAX_PWM_TICKS = (SystemCoreClock / (PWM_HZ * PWM_PRESECALER_DEFAULT)),
// TICKLE_TIMES = 100 ,
TICKLE_TIMES = 10 , // Massively reduced May 2020 in connection with handbrake implementation.
WATCHDOG_RELOAD = (TIMEOUT_SECONDS * 8); // WatchDog counter ticked down in 8Hz loop
const double PI = 4.0 * atan(1.0),
TWOPI = 8.0 * atan(1.0);
/* End of Please Do Not Alter these */
enum {COM_SOURCES, COM1, COM2, HAND, RC_IN1, RC_IN2, RC_IN_BOTH, THEEND} ; // RC_IN_BOTH new Dec 2019
// List user settable firmware bytes in EEROM
enum {MOTADIR, MOTBDIR, MOTAPOLES, MOTBPOLES, ISHUNTA, ISHUNTB, POT_REGBRAKE_RANGE, SVO1, SVO2, RCIN1, RCIN2,
COMM_SRC, BOARD_ID, TOP_SPEED, WHEELDIA, MOTPIN, WHEELGEAR,
RCI1_TRIM, RCI2_TRIM, RCIN_REGBRAKE_RANGE, RCIN_STICK_ATTACK, // RC in trims new Dec 2019
RCIN1REVERSE, RCIN2REVERSE, NOM_SYSTEM_VOLTS, BRAKE_EFFECTIVENESS, BAUD, FUT11,
FUT12, FUT13, FUT14, FUT16,} ; // These represent byte address offsets in 24LC64 rom user settable firmware settings
enum { // List of fault numbers currently dealt with by error handler
FAULT_0,
FAULT_EEPROM,
FAULT_BOARD_ID,
FAULT_COM_LINE_LEN,
FAULT_COM_LINE_NOMATCH,
FAULT_COM_LINE_LEN_PC,
FAULT_COM_LINE_LEN_TS,
FAULT_COM_LINE_NOMATCH_PC,
FAULT_COM_LINE_NOMATCH_TS,
FAULT_UNRECOGNISED_STATE,
FAULT_MAX,
NUMOF_REPORTABLE_TS_ERRORS
} ; // List of fault numbers currently dealt with by error handler
class error_handling_Jan_2019
{
int32_t ESC_fault[NUMOF_REPORTABLE_TS_ERRORS] ; // Some number of reportable error codes, accessible through set and read members
public:
error_handling_Jan_2019 () { // default constructor
for (int i = 0; i < (sizeof(ESC_fault) / sizeof(int32_t)); i++)
ESC_fault[i] = 0;
}
void set (uint32_t, int32_t) ;
void clr (uint32_t) ;
uint32_t read (uint32_t) ;
bool all_good () ;
void report_any (bool) ; // retain ? true or false
} ;
enum {SOURCE_PC, SOURCE_TS} ;
const int BROADCAST = '\r';
const int MAX_CLI_PARAMS = 12;
const int MAX_CMD_LEN = 220;
struct parameters { // Used in serial comms with pc and other controller (e.g. touch-screen)
struct kb_command const * command_list;
BufferedSerial * com; // pc or com2
int32_t position_in_list, numof_dbls, target_unit, source, numof_menu_items;
double dbl[MAX_CLI_PARAMS];
bool respond, resp_always;
} ;
enum {ZONE_BRAKE, ZONE_COAST, ZONE_DRIVE} ;
class RC_stick_info { // info read concerning stick positions
public:
double raw, // range 0.0 to 1.0 after clipping and correction
deflection; // how far from centre or min positon
double brake_effort, // braking effort
drive_effort; // driving effort
uint32_t zone; // in drive, coast or braking zone (if drive, direction in 'stick_implied_motor_direction')
uint32_t chan_mode;
int32_t stick_implied_motor_direction; // -1, 0, +1 but could be in drive, coast or brake regions
bool active;
RC_stick_info () {
active = false;
chan_mode = 0;
zone = ZONE_COAST;
drive_effort = brake_effort = 0.0;
}
} ;
class cli_2019 { // cli Command Line Interpreter, two off, 1 for pc comms, other touch-screen controller comms
struct kb_command const * commandlist ;
uint32_t clindex;
char cmdline[MAX_CMD_LEN + 8];
char * cmdline_ptr;
parameters a ;
public:
cli_2019 (BufferedSerial * comport, kb_command const * list, uint32_t list_len, uint32_t source) {
a.com = comport ;
a.command_list = commandlist = list ;
a.numof_menu_items = list_len ;
a.source = source ;
cmdline_ptr = cmdline;
clindex = 0;
if (source == SOURCE_PC)
a.resp_always = true;
else
a.resp_always = false;
} ;
void core () ;
void flush () ; // Used to clear startup transient garbage
} ;
const uint32_t MAX_I2C_DEVICES = 6;
class eeprom_settings {
I2C i2c;
uint32_t errors;
uint32_t i2c_device_count;
uint32_t i2c_device_list[MAX_I2C_DEVICES+1]; // max 12 i2c devices
char settings [36];
double rpm2mphdbl, user_brake_rangedbl, Vnomdbl, brake_eff, top_speeddbl;
bool rd_24LC64 (uint32_t start_addr, char * dest, uint32_t length) ;
bool wr_24LC64 (uint32_t start_addr, char * dest, uint32_t length) ;
bool set_24LC64_internal_address (int start_addr) ;
bool ack_poll () ;
void update_dbls () ;
public:
eeprom_settings (PinName sda, PinName scl); // Constructor
bool do_we_have_i2c (uint32_t x) ;
char rd (uint32_t) ; // Read one setup char value from private buffer 'settings'
bool wr (char, uint32_t) ; // Write one setup char value to private buffer 'settings'
bool save () ; // Write 'settings' buffer to EEPROM
bool set_defaults (); // Put default settings into EEPROM and local buffer
uint32_t errs () ; // Return errors
const char * t (uint32_t);
uint32_t min (uint32_t) ;
uint32_t max (uint32_t) ;
uint32_t def (uint32_t) ;
bool in_range (char val, uint32_t p) ;
void edit (double * dbl, uint32_t numof_dbls) ;
double user_brake_range () ;
double brake_effectiveness () ;
double top_speed () ;
double Vnom () ;
double rpm2mph () ;
double rpm2mph (double) ;
uint32_t baud ();
} ;
struct optpar {
int32_t min, max, de_fault; // min, max, default
const char * txt; // description
} ;
#endif