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
Diff: 24LC64_eeprom.cpp
- Revision:
- 12:d1d21a2941ef
- Parent:
- 3:ecb00e0e8d68
- Child:
- 13:ef7a06fa11de
--- 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);
}
+