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
24LC64_eeprom.cpp
- Committer:
- JonFreeman
- Date:
- 2019-03-04
- Revision:
- 12:d1d21a2941ef
- Parent:
- 3:ecb00e0e8d68
File content as of revision 12:d1d21a2941ef:
#include "mbed.h"
#include "DualBLS.h"
#include "BufferedSerial.h"
extern BufferedSerial pc;
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;
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;
while (poll_count++ < poll_tries && !i2cfree) {
i2c.start ();
if (i2c.write(addr_wr) == ACK)
i2cfree = true;
else
wait_ms (1);
}
return i2cfree;
}
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");
i2c.stop();
return false;
}
int err = 0;
if (i2c.write(start_addr >> 8) != ACK) err++;
if (i2c.write(start_addr & 0xff) != ACK) err++;
if (err) {
pc.printf ("In set_24LC64_internal_address, Believe Device present, failed in writing 2 mem addr bytes %d\r\n", err);
i2c.stop();
return false;
}
return true;
}
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);
return false;
}
ack_poll ();
if (!set_24LC64_internal_address (start_addr)) {
pc.printf ("In wr_24LC64, Believe Device present, failed in writing 2 mem addr bytes %d\r\n", err);
return false;
}
while(length--)
err += ACK - i2c.write(*source++);
i2c.stop();
if (err) {
pc.printf ("in wr_24LC64, device thought good, mem addr write worked, failed writing string\r\n");
return false;
}
pc.printf ("In wr_24LC64 No Errors Found!\r\n");
return true;
}
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;
}
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;
settings[i] = c;
return true;
}
bool eeprom_settings::save () { // Write 'settings' buffer to EEPROM
return wr_24LC64 (0, settings, 32);
}