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
Diff: main.cpp
- Revision:
- 7:6deaeace9a3e
- Parent:
- 6:f289a49c1eae
- Child:
- 8:93203f473f6e
--- a/main.cpp Tue Jun 05 07:19:39 2018 +0000 +++ b/main.cpp Sun Jun 17 06:59:37 2018 +0000 @@ -6,7 +6,7 @@ /* 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 - and rerouted to PC_13 at InterruptIn on T1 (ports A and B I think) not workable + Also new LMT01 temperature sensor routed to T1 - and rerouted to PC_13 as InterruptIn on T1 (ports A and B I think) not workable */ @@ -28,154 +28,11 @@ */ -//#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 - -// Port A -> MotorA, Port B -> MotorB -const uint16_t -AUL = 1 << 0, // Feb 2018 Now using DGD21032 mosfet drivers via 74HC00 pwm gates (low side) - GOOD, works well with auto-tickle of high side drivers -AVL = 1 << 6, // These are which port bits connect to which mosfet driver -AWL = 1 << 4, - -AUH = 1 << 1, -AVH = 1 << 7, -AWH = 1 << 8, - -AUV = AUH | AVL, // Each of 6 possible output energisations made up of one hi and one low -AVU = AVH | AUL, -AUW = AUH | AWL, -AWU = AWH | AUL, -AVW = AVH | AWL, -AWV = AWH | AVL, - -KEEP_L_MASK_A = AUL | AVL | AWL, -KEEP_H_MASK_A = AUH | AVH | AWH, - -BRA = AUL | AVL | AWL, // All low side switches on (and all high side off) for braking - -BUL = 1 << 0, // Likewise for MotorB but different port bits on different port -BVL = 1 << 1, -BWL = 1 << 2, - -BUH = 1 << 10, -BVH = 1 << 12, -BWH = 1 << 13, - -BUV = BUH | BVL, -BVU = BVH | BUL, -BUW = BUH | BWL, -BWU = BWH | BUL, -BVW = BVH | BWL, -BWV = BWH | BVL, - -KEEP_L_MASK_B = BUL | BVL | BWL, -KEEP_H_MASK_B = BUH | BVH | BWH, - -BRB = BUL | BVL | BWL, - -PORT_A_MASK = AUL | AVL | AWL | AUH | AVH | AWH, // NEW METHOD FOR DGD21032 MOSFET DRIVERS -PORT_B_MASK = BUL | BVL | BWL | BUH | BVH | BWH; - -PortOut MotA (PortA, PORT_A_MASK); // Activate output ports to motor drivers -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 -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 -// Pin 6 PH1-OSC_OUT NET PH1 -// Pin 7 NRST NET NRST -AnalogIn Ain_DriverPot (PC_0); // Pin 8 Spare Analogue in, net SAIN fitted with external pull-down -AnalogIn Ain_SystemVolts (PC_1); // Pin 9 -AnalogIn Motor_A_Current (PC_2); // Pin 10 -AnalogIn Motor_B_Current (PC_3); // Pin 11 -// Pin 12 VSSA/VREF- NET GND -// Pin 13 VDDA/VREF+ NET +3V3 -// Pin 14 Port_A AUL -// Pin 15 Port_A AUH -// Pins 16, 17 BufferedSerial pc -BufferedSerial pc (PA_2, PA_3, 512, 4, NULL); // Pins 16, 17 tx, rx to pc via usb lead -// Pin 18 VSS NET GND -// Pin 19 VDD NET +3V3 -// Pin 20 Port_A AWL -// Pin 21 DigitalOut led1(LED1); -DigitalOut LED (PA_5); // Pin 21 -// Pin 22 Port_A AVL -// Pin 23 Port_A AVH -InterruptIn MBH2 (PC_4); // Pin 24 -InterruptIn MBH3 (PC_5); // Pin 25 -// Pin 26 Port_B BUL -// Pin 27 Port_B BVL -// Pin 28 Port_B BWL -// Pin 29 Port_B BUH -// Pin 30 VCAP1 -// Pin 31 VSS -// Pin 32 VDD -// Pin 33 Port_B BVH -// Pin 34 Port_B BWH -DigitalOut T4 (PB_14); // Pin 35 -DigitalOut T3 (PB_15); // Pin 36 -// BufferedSerial com2 pins 37 Tx, 38 Rx -BufferedSerial com2 (PC_6, PC_7); // Pins 37, 38 tx, rx to XBee module -FastPWM A_MAX_V_PWM (PC_8, 1), // Pin 39 pwm3/3 - A_MAX_I_PWM (PC_9, 1); // pin 40, prescaler value pwm3/4 -//InterruptIn MotB_Hall (PA_8); // Pin 41 -// Pin 41 Port_A AWH -// BufferedSerial com3 pins 42 Tx, 43 Rx -//InterruptIn tryseredge (PA_9); -BufferedSerial com3 (PA_9, PA_10); // Pins 42, 43 tx, rx to any aux module -// PA_9 is Tx. I wonder, can we also use InterruptIn on this pin to generate interrupts on tx bit transitions ? Let's find out ! -// No. - -// Feb 2018 Pins 44 and 45 now liberated, could use for serial or other uses -//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 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 -// Pin 49 SWCLK - -//Was DigitalOut T5 (PA_15); // Pin 50 -DigitalIn T5 (PA_15); // Pin 50 now fwd/rev from remote control box if fitted -InterruptIn MAH1 (PC_10); // Pin 51 -InterruptIn MAH2 (PC_11); // Pin 52 -InterruptIn MAH3 (PC_12); // Pin 53 -InterruptIn MBH1 (PD_2); // Pin 54 -DigitalOut T6 (PB_3); // Pin 55 -FastPWM B_MAX_V_PWM (PB_4, 1), // Pin 56 pwm3/3 - B_MAX_I_PWM (PB_5, 1); // pin 57, prescaler value pwm3/4 - -I2C i2c (PB_7, PB_6); // Pins 58, 59 For 24LC64 eeprom -// Pin 60 BOOT0 - -// Servo pins, 2 off. Configured as Input to read radio control receiver -// If used as servo output, code gives pin to 'Servo' - seems to work -InterruptIn Servo1_i (PB_8); // Pin 61 to read output from rc rx -InterruptIn Servo2_i (PB_9); // Pin 62 to read output from rc rx - -// Pin 63 VSS -// Pin 64 VDD -// SYSTEM CONSTANTS - +#if defined (TARGET_NUCLEO_F401RE) // CPU in 64 pin LQFP +#include "F401RE.h" #endif -#if defined (TARGET_NUCLEO_F446ZE) +#if defined (TARGET_NUCLEO_F446ZE) // CPU in 144 pin LQFP +#include "F446ZE.h" #endif /* Global variable declarations */ volatile uint32_t fast_sys_timer = 0; // gets incremented by our Ticker ISR every VOLTAGE_READ_INTERVAL_US @@ -188,11 +45,14 @@ 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; +bool eeprom_flag; // gets set according to 24LC674 being found or not +bool mode_good_flag = 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; + double rpm2mph = 0.0; // gets calculated from eeprom mode entries if present /* End of Global variable declarations */ Ticker tick_vread; // Device to cause periodic interrupts, used to time voltage readings etc @@ -364,7 +224,7 @@ motor MotorA (&MotA, &A_MAX_V_PWM, &A_MAX_I_PWM, A_tabl, AHarr); motor MotorB (&MotB, &B_MAX_V_PWM, &B_MAX_I_PWM, B_tabl, BHarr); -motor * MotPtr[8]; // Array of pointers to some number of motor objects +//motor * MotPtr[8]; // Array of pointers to some number of motor objects motor::motor (PortOut * P , FastPWM * _maxV_ , FastPWM * _maxI_ , const uint16_t * lutptr, InterruptIn ** Hall) // Constructor { // Constructor @@ -700,7 +560,9 @@ } } -extern void command_line_interpreter () ; +extern void setup_comms () ; +extern void command_line_interpreter_pc () ; +extern void command_line_interpreter_loco () ; extern int check_24LC64 () ; // Call from near top of main() to init i2c bus extern bool wr_24LC64 (int mem_start_addr, char * source, int length) ; extern bool rd_24LC64 (int mem_start_addr, char * dest, int length) ; @@ -719,6 +581,12 @@ return IAm; } +double mph (int rpm) { + if (mode_good_flag) { + return rpm2mph * (double) rpm; + } + return -1.0; +} int main() { @@ -726,8 +594,8 @@ MotA = 0; // Output all 0s to Motor drive ports A and B MotB = 0; - MotPtr[0] = &MotorA; // Pointers to motor class objects - MotPtr[1] = &MotorB; +// MotPtr[0] = &MotorA; // Pointers to motor class objects +// MotPtr[1] = &MotorB; Temperature_pin.fall (&temp_sensor_isr); Temperature_pin.mode (PullUp); @@ -767,23 +635,18 @@ pc.baud (9600); com3.baud (1200); com2.baud (19200); + setup_comms (); + IAm = '0'; 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"); + eeprom_flag = false; } else { // Found 24LC64 memory on I2C + eeprom_flag = true; bool k; -// static const char ramtst[] = "I found the man sir!"; -// j = wr_24LC64 (0x1240, (char*)ramtst, strlen(ramtst)); -// for (int i = 0; i < TXTBUFSIZ; i++) buff[i] = 0; // Clear buffer -// // need a way to check i2c busy - YES implemented ack_poll -// 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, mode_bytes, 32); -// if (k) -// com2.printf ("Good read from eeprom\r\n"); if (!k) com2.printf ("Error reading from eeprom\r\n"); @@ -796,11 +659,16 @@ // else // com2.printf ("%2x Good %s\r\n", buff[i], option_list[i].t); } - IAm = '0'; + rpm2mph = 0.0; if (err == 0) { + mode_good_flag = true; MotorA.direction_set (mode_bytes[MOTADIR]); MotorB.direction_set (mode_bytes[MOTBDIR]); IAm = mode_bytes[ID]; + rpm2mph = 60.0 // to Motor Revs per hour; + * ((double)mode_bytes[MOTPIN] / (double)mode_bytes[WHEELGEAR]) // Wheel revs per hour + * PI * ((double)mode_bytes[WHEELDIA] / 1000.0) // metres per hour + * 39.37 / (1760.0 * 36.0); // miles per hour } // Alternative ID 1 to 9 // com2.printf ("Alternative ID = 0x%2x\r\n", buff[6]); @@ -826,7 +694,7 @@ 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 +// 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; /* @@ -851,10 +719,12 @@ break; } */ - pc.printf ("Ready to go!, wheel gear in position %d\r\n", WHEELGEAR); +// pc.printf ("Ready to go!, wheel gear in position %d\r\n", WHEELGEAR); + pc.printf ("About to start!\r\n"); 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 + command_line_interpreter_pc () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true + command_line_interpreter_loco () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true AtoD_reader (); // Performs A to D conversions at rate set by ticker interrupts } loop_flag = false; // Clear flag set by ticker interrupt handler @@ -877,12 +747,12 @@ eighth_sec_count = 0; MotorA.current_calc (); // Updates readings in MotorA.I.min, MotorA.I.ave and MotorA.I.max MotorB.current_calc (); - if (temp_sensor_exists) { +/* 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)