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:
12:d1d21a2941ef
Parent:
3:ecb00e0e8d68
--- a/24LC64_eeprom.cpp	Sat Jan 19 11:45:01 2019 +0000
+++ b/24LC64_eeprom.cpp	Mon Mar 04 17:51:08 2019 +0000
@@ -1,16 +1,129 @@
 #include "mbed.h"
-//#include "rtos.h"
+#include "DualBLS.h"
 #include "BufferedSerial.h"
 extern  BufferedSerial pc;
-extern  I2C i2c;
+extern  error_handling_Jan_2019     ESC_Error    ;         //  Provides array usable to store error codes.
     //  Code for 24LC64 8k x 8 bit eeprom
     //  Code based on earlier work using memory FM24W256, also at i2c address 0xa0;
- 
+
 const int addr_rd = 0xa1;  //  set bit 0 for read, clear bit 0 for write
 const int addr_wr = 0xa0;  //  set bit 0 for read, clear bit 0 for write
 const int ACK     = 1;
 
-bool    ack_poll    ()  {   //  wait short while for any previous memory operation to complete
+struct  optpar  {
+    int min, max, def;  //  min, max, default
+    const char * t;     //  description
+}   ;
+struct  optpar option_list2[] = {
+    {0, 1, 1, "MotorA direction 0 or 1"},
+    {0, 1, 0, "MotorB direction 0 or 1"},
+    {4, 8, 8, "MotorA poles 4 or 6 or 8"},
+    {4, 8, 8, "MotorB poles 4 or 6 or 8"},
+    {1, 4, 1, "MotorA 0R05 ohm current shunt resistors 1 to 4"},
+    {1, 4, 1, "MotorB 0R05 ohm current shunt resistors 1 to 4"},
+    {0, 1, 0, "Servo1 0 = Not used, 1= Output"},
+    {0, 1, 0, "Servo2 0 = Not used, 1= Output"},
+    {0, 1, 0, "RC Input1 0 = Not used, 1= Output"},
+    {0, 1, 0, "RC Input2 0 = Not used, 1= Output"},
+    {2, 5, 2, "Command source 2= COM2 (Touch Screen), 3= Pot, 4= RC Input1, 5= RC Input2"},
+    {'1', '9', '0', "Alternative ID ascii '1' to '9'"}, //  defaults to '0' before eerom setup for first time
+    {10, 250, 60,   "Top speed MPH * 10 range 1.0 to 25.0"},    //  New Jan 2019 TOP_SPEED
+    {50, 253, 98,   "Wheel diameter mm"},   //  New 01/06/2018
+    {10, 253, 27,   "Motor pinion"},   //  New 01/06/2018
+    {50, 253, 85,   "Wheel gear"},   //  New 01/06/2018
+    {0, 100, 0, "Future 1"},
+    {0, 100, 0, "Future 2"},
+    {0, 100, 0, "Future 3"},
+    {0, 100, 0, "Future 4"},
+    {0, 100, 0, "Future 5"},
+}   ;
+
+const   int    numof_eeprom_options2    = sizeof(option_list2) / sizeof (struct optpar);
+
+
+
+
+/*
+class   eeprom_settings {
+    I2C i2c;
+    uint32_t    errors;
+    char        settings    [36];
+    bool        rd_24LC64  (int start_addr, char * dest, int length)    ;
+    bool        wr_24LC64  (int start_addr, char * dest, int length)    ;
+    bool        set_24LC64_internal_address (int    start_addr) ;
+    bool        ack_poll    ()  ;
+  public:
+    eeprom_settings (PinName sda, PinName scl); //  Constructor
+    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
+    uint32_t    errs    ()  ;               //  Return errors
+}   ;
+*/
+
+bool        eeprom_settings::set_defaults    () {         //  Put default settings into EEPROM and local buffer
+    for (int i = 0; i < numof_eeprom_options2; i++)
+        settings[i] = option_list2[i].def;       //  Load defaults and 'Save Settings'
+    return  save    ();
+}
+
+uint32_t    eeprom_settings::errs   ()  {
+    return  errors;
+}
+
+//  Use :   eeprom_settings (SDA_PIN, SCL_PIN);
+eeprom_settings::eeprom_settings    (PinName sda, PinName scl) : i2c(sda, scl)  //  Constructor
+{
+    errors = 0;
+    for (int i = 0; i < 36; i++)
+        settings[i] = 0;
+    i2c.frequency(400000);      //  Speed 400000 max.
+    int last_found = 0, q;      //  Note address bits 3-1 to match addr pins on device
+    for (int i = 0; i < 255; i += 2)    {   //  Search for devices at all possible i2c addresses
+        i2c.start();
+        q = i2c.write(i);   //  may return error code 2 when no start issued
+        switch  (q) {
+            case    ACK:
+                pc.printf   ("I2C device found at 0x%x\r\n", i);
+                last_found = i;
+            case    2:      //  Device not seen at this address
+            break;
+            default:
+                pc.printf   ("Unknown error %d in check_24LC64\r\n", q);
+                errors |= 512;
+            break;
+        }
+    }
+    i2c.stop();
+    if  (errors || last_found != 0xa0)    {
+        pc.printf   ("Error - EEPROM not seen %d\r\n", errors);
+        errors |= 0xa0;
+        ESC_Error.set   (FAULT_EEPROM, errors);                      //  Set FAULT_EEPROM bits if 24LC64 problem
+    }
+    else    {   //  Found 24LC64 memory on I2C. Attempt to load settings from EEPROM
+        errors = 0;
+        if  (!rd_24LC64   (0, settings, 32))
+            ESC_Error.set   (FAULT_EEPROM, 2);                      //  Set FAULT_EEPROM bit 1 if 24LC64 problem
+        for (int i = 0; i < numof_eeprom_options2; i++) {
+            if  ((settings[i] < option_list2[i].min) || (settings[i] > option_list2[i].max))  {
+                pc.printf   ("EEROM error with %s\r\n", option_list2[i].t);
+                errors++;
+            }
+        }
+    }
+    ESC_Error.set   (FAULT_EEPROM, errors);  //  sets nothing if 0
+    if  (errors > 1) {
+        pc.printf   ("Bad settings found at startup. Restoring defaults\r\n");
+        for (int i = 0; i < numof_eeprom_options2; i++)
+            settings[i] = option_list2[i].def;       //  Load defaults and 'Save Settings'
+        if  (!wr_24LC64  (0, settings, 32))         //  Save settings
+            pc.printf   ("Error saving EEPROM in mode19\r\n");
+    }
+    else    //  0 or 1 error max found
+        pc.printf   ("At startup, settings errors = %d\r\n", errors);
+}       //  endof constructor
+    
+bool    eeprom_settings::ack_poll    ()  {   //  wait short while for any previous memory operation to complete
     const int poll_tries    = 40;
     int poll_count = 0;
     bool    i2cfree = false;
@@ -19,14 +132,12 @@
         if  (i2c.write(addr_wr) == ACK)
             i2cfree = true;
         else
-//            Thread::wait(1);   //   1ms
             wait_ms   (1);
     }
-//    pc.printf   ("ack_poll, count = %d, i2cfree = %s\r\n", poll_count, i2cfree ? "true" : "false");
     return  i2cfree;
 }
 
-bool    set_24LC64_internal_address (int    start_addr)   {
+bool    eeprom_settings::set_24LC64_internal_address (int    start_addr)   {
     if  (!ack_poll())
     {
         pc.printf   ("Err in set_24LC64_internal_address, no ACK writing device address byte\r\n");
@@ -44,7 +155,29 @@
     return  true;
 }
 
-bool    wr_24LC64  (int start_addr, char * source, int length)   {
+bool eeprom_settings::rd_24LC64  (int start_addr, char * dest, int length)   {
+    int acknak = ACK;
+    if(length < 1)
+        return false;
+    if  (!set_24LC64_internal_address   (start_addr))   {
+        pc.printf   ("In rd_24LC64, failed to set_ramaddr\r\n");
+        return  false;
+    }
+    i2c.start();
+    if  (i2c.write(addr_rd) != ACK) {
+        pc.printf   ("Errors in rd_24LC64 sending addr_rd\r\n");
+        return  false;
+    }
+    while(length--) {
+        if(length == 0)
+            acknak = 0;
+        *dest++ = i2c.read(acknak);
+    }
+    i2c.stop();
+    return  true;
+}
+
+bool    eeprom_settings::wr_24LC64  (int start_addr, char * source, int length)   {
     int err = 0;
     if(length < 1 || length > 32)   {
         pc.printf   ("Length out of range %d in wr_24LC64\r\n", length);
@@ -66,46 +199,22 @@
     return  true;
 }
 
-bool rd_24LC64  (int start_addr, char * dest, int length)   {
-    int acknak = ACK;
-    if(length < 1)
-        return false;
-    if  (!set_24LC64_internal_address   (start_addr))   {
-        pc.printf   ("In rd_24LC64, failed to set_ramaddr\r\n");
-        return  false;
+char    eeprom_settings::rd  (uint32_t i)  {           //  Read one setup char value from private buffer 'settings'
+    if  (i > 31)    {
+        pc.printf   ("ERROR Attempt to read setting %d\r\n");
+        return  0;
     }
-    i2c.start();
-    if  (i2c.write(addr_rd) != ACK) {
-        pc.printf   ("Errors in rd_24LC64 sending addr_rd\r\n");
+    return  settings[i];
+}
+
+bool    eeprom_settings::wr  (char c, uint32_t i)  {           //  Read one setup char value from private buffer 'settings'
+    if  (i > 31)
         return  false;
-    }
-    while(length--) {
-        if(length == 0)
-            acknak = 0;
-        *dest++ = i2c.read(acknak);
-    }
-    i2c.stop();
+    settings[i] = c;
     return  true;
 }
 
-int check_24LC64   ()  {     //  Call from near top of main() to init i2c bus
-//    i2c.frequency(400000);      //  Speed 400000 max.
-    i2c.frequency(400000);      //  Speed 400000 max.
-    int last_found = 0, q;      //  Note address bits 3-1 to match addr pins on device
-    for (int i = 0; i < 255; i += 2)    {   //  Search for devices at all possible i2c addresses
-        i2c.start();
-        q = i2c.write(i);   //  may return error code 2 when no start issued
-        switch  (q) {
-            case    ACK:
-                pc.printf   ("I2C device found at 0x%x\r\n", i);
-                last_found = i;
-            case    2:      //  Device not seen at this address
-            break;
-            default:
-                pc.printf   ("Unknown error %d in check_24LC64\r\n", q);
-            break;
-        }
-    }
-    i2c.stop();
-    return  last_found;
+bool    eeprom_settings::save    ()  {               //  Write 'settings' buffer to EEPROM
+    return  wr_24LC64   (0, settings, 32);
 }
+