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:
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)