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); }