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

Committer:
JonFreeman
Date:
Sun Aug 16 14:13:19 2020 +0000
Revision:
17:cc9b854295d6
Parent:
16:d1e4b9ad3b8b
August 2020. Checked Radio Control input ops.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JonFreeman 0:435bf84ce48a 1 #include "mbed.h"
JonFreeman 13:ef7a06fa11de 2 #include "STM3_ESC.h"
JonFreeman 0:435bf84ce48a 3 #include "BufferedSerial.h"
JonFreeman 0:435bf84ce48a 4 extern BufferedSerial pc;
JonFreeman 12:d1d21a2941ef 5 extern error_handling_Jan_2019 ESC_Error ; // Provides array usable to store error codes.
JonFreeman 3:ecb00e0e8d68 6 // Code for 24LC64 8k x 8 bit eeprom
JonFreeman 0:435bf84ce48a 7 // Code based on earlier work using memory FM24W256, also at i2c address 0xa0;
JonFreeman 12:d1d21a2941ef 8
JonFreeman 16:d1e4b9ad3b8b 9 const int addr_rd = 0xa1; // set bit 0 for read, clear bit 0 for write 24LC64
JonFreeman 16:d1e4b9ad3b8b 10 const int addr_wr = 0xa0; // set bit 0 for read, clear bit 0 for write 24LC64
JonFreeman 16:d1e4b9ad3b8b 11 const int ACK = 1;
JonFreeman 16:d1e4b9ad3b8b 12 /*struct optpar {
JonFreeman 16:d1e4b9ad3b8b 13 int min, max, de_fault; // min, max, default
JonFreeman 16:d1e4b9ad3b8b 14 const char * txt; // description
JonFreeman 12:d1d21a2941ef 15 } ;
JonFreeman 16:d1e4b9ad3b8b 16 */
JonFreeman 16:d1e4b9ad3b8b 17 struct optpar option_list[] = {
JonFreeman 16:d1e4b9ad3b8b 18 {0, 1, 1, "MotorA direction [0 or 1]"}, // MOTADIR
JonFreeman 16:d1e4b9ad3b8b 19 {0, 1, 0, "MotorB direction [0 or 1]"}, // MOTBDIR
JonFreeman 16:d1e4b9ad3b8b 20 {4, 8, 8, "MotorA poles 4 or 6 or 8"}, // MOTAPOLES
JonFreeman 16:d1e4b9ad3b8b 21 {4, 8, 8, "MotorB poles 4 or 6 or 8"}, // MOTBPOLES
JonFreeman 16:d1e4b9ad3b8b 22 {1, 4, 1, "MotorA 0R05 shunt Rs 1 to 4"}, // ISHUNTB
JonFreeman 16:d1e4b9ad3b8b 23 {1, 4, 1, "MotorB 0R05 shunt Rs 1 to 4"}, // ISHUNTB
JonFreeman 16:d1e4b9ad3b8b 24 {10, 50, 20, "POT_REGBRAKE_RANGE percentage 10 to 50"}, // POT_REGBRAKE_RANGE
JonFreeman 16:d1e4b9ad3b8b 25 {0, 1, 0, "Servo1 out 0 = Disabled, 1= Output enabled"}, // SVO1
JonFreeman 16:d1e4b9ad3b8b 26 {0, 1, 0, "Servo2 out 0 = Disabled, 1= Output enabled"}, // SVO2
JonFreeman 16:d1e4b9ad3b8b 27 {0, 2, 0, "RC Input1 0 = Not used, 1= Uni_dir, 2= Bi_dir"}, // RCIN1
JonFreeman 16:d1e4b9ad3b8b 28 {0, 2, 0, "RC Input2 0 = Not used, 1= Uni_dir, 2= Bi_dir"}, // RCIN2
JonFreeman 16:d1e4b9ad3b8b 29 {2, 6, 2, "Command source 2= COM2 (Touch Screen), 3= Pot, 4= RCIn1, 5= RCIn2, 6=RCin_both"}, // COMM_SRC
JonFreeman 16:d1e4b9ad3b8b 30 {'1', '9', '0', "Alternative ID ascii '1' to '9'"}, // BOARD_ID defaults to '0' before eerom setup for first time
JonFreeman 16:d1e4b9ad3b8b 31 {10, 250, 60, "Top speed MPH, range 1.0 to 25.0"}, // New Jan 2019 TOP_SPEED
JonFreeman 16:d1e4b9ad3b8b 32 {50, 253, 98, "Wheel diameter mm"}, // New 01/06/2018
JonFreeman 16:d1e4b9ad3b8b 33 {10, 253, 27, "Motor pinion"}, // New 01/06/2018
JonFreeman 16:d1e4b9ad3b8b 34 {50, 253, 85, "Wheel gear"}, // New 01/06/2018 ** NOTE this and above two used to calculate RPM to MPH **
JonFreeman 16:d1e4b9ad3b8b 35 {0, 255, 12, "RC in 1 trim"}, // New Dec 2019 RCI1_TRIM read as 2's complement (-128 to +127), user enters -128 to +127
JonFreeman 16:d1e4b9ad3b8b 36 {0, 255, 12, "RC in 2 trim"}, // New Dec 2019 RCI2_TRIM read as 2's complement (-128 to +127), user enters -128 to +127
JonFreeman 16:d1e4b9ad3b8b 37 {10, 50, 20, "RCIN_REGBRAKE_RANGE stick range percent 10 to 50"}, // RCIN_REGBRAKE_RANGE
JonFreeman 16:d1e4b9ad3b8b 38 {10, 90, 50, "RCIN_STICK_ATTACK rate percent 10 to 90"}, // RCIN_STICK_ATTACK
JonFreeman 16:d1e4b9ad3b8b 39 {0, 1, 0, "RCIN1 direction swap 0 normal, 1 reverse"}, // RCIN1REVERSE
JonFreeman 16:d1e4b9ad3b8b 40 {0, 1, 0, "RCIN2 direction swap 0 normal, 1 reverse"}, // RCIN2REVERSE
JonFreeman 16:d1e4b9ad3b8b 41 {11, 63, 48, "Nominal system voltage, used to calculate current scaling"}, // NOM_SYSTEM_VOLTS
JonFreeman 16:d1e4b9ad3b8b 42 {5, 91, 90, "Brake Effectiveness percentage"},
JonFreeman 16:d1e4b9ad3b8b 43 {1, 5, 1, "Baud rate, [1=9k6, 2=19k2, 3=38k4, 4=78k6, 5=115k2] = "}, // BAUD 1=9k6, 2=19k2, 3=38k4, 4=78k6, 5=115k2
JonFreeman 16:d1e4b9ad3b8b 44 {0, 100, 0, "Future 11"},
JonFreeman 16:d1e4b9ad3b8b 45 {0, 100, 0, "Future 12"},
JonFreeman 16:d1e4b9ad3b8b 46 {0, 100, 0, "Future 13"},
JonFreeman 16:d1e4b9ad3b8b 47 {0, 100, 0, "Future 14"},
JonFreeman 16:d1e4b9ad3b8b 48 {0, 100, 0, "Future 15"},
JonFreeman 16:d1e4b9ad3b8b 49 {0, 100, 0, "Future 16"},
JonFreeman 12:d1d21a2941ef 50 } ;
JonFreeman 12:d1d21a2941ef 51
JonFreeman 16:d1e4b9ad3b8b 52 const int numof_eeprom_options = sizeof(option_list) / sizeof (struct optpar);
JonFreeman 12:d1d21a2941ef 53
JonFreeman 12:d1d21a2941ef 54
JonFreeman 12:d1d21a2941ef 55
JonFreeman 12:d1d21a2941ef 56
JonFreeman 12:d1d21a2941ef 57 /*
JonFreeman 12:d1d21a2941ef 58 class eeprom_settings {
JonFreeman 12:d1d21a2941ef 59 I2C i2c;
JonFreeman 12:d1d21a2941ef 60 uint32_t errors;
JonFreeman 14:acaa1add097b 61 uint32_t i2c_device_count;
JonFreeman 14:acaa1add097b 62 uint32_t i2c_device_list[12]; // max 12 i2c devices
JonFreeman 12:d1d21a2941ef 63 char settings [36];
JonFreeman 16:d1e4b9ad3b8b 64 double rpm2mphdbl, user_brake_rangedbl, Vnomdbl;
JonFreeman 16:d1e4b9ad3b8b 65 bool rd_24LC64 (uint32_t start_addr, char * dest, uint32_t length) ;
JonFreeman 16:d1e4b9ad3b8b 66 bool wr_24LC64 (uint32_t start_addr, char * dest, uint32_t length) ;
JonFreeman 12:d1d21a2941ef 67 bool set_24LC64_internal_address (int start_addr) ;
JonFreeman 12:d1d21a2941ef 68 bool ack_poll () ;
JonFreeman 12:d1d21a2941ef 69 public:
JonFreeman 12:d1d21a2941ef 70 eeprom_settings (PinName sda, PinName scl); // Constructor
JonFreeman 14:acaa1add097b 71 bool do_we_have_i2c (uint32_t x) ;
JonFreeman 12:d1d21a2941ef 72 char rd (uint32_t) ; // Read one setup char value from private buffer 'settings'
JonFreeman 12:d1d21a2941ef 73 bool wr (char, uint32_t) ; // Write one setup char value to private buffer 'settings'
JonFreeman 12:d1d21a2941ef 74 bool save () ; // Write 'settings' buffer to EEPROM
JonFreeman 16:d1e4b9ad3b8b 75 bool set_defaults (); // Put default settings into EEPROM and local buffer
JonFreeman 12:d1d21a2941ef 76 uint32_t errs () ; // Return errors
JonFreeman 16:d1e4b9ad3b8b 77 const char * t (uint32_t);
JonFreeman 16:d1e4b9ad3b8b 78 int min (uint32_t) ;
JonFreeman 16:d1e4b9ad3b8b 79 int max (uint32_t) ;
JonFreeman 16:d1e4b9ad3b8b 80 int def (uint32_t) ;
JonFreeman 16:d1e4b9ad3b8b 81 bool in_range (char val, uint32_t p) ;
JonFreeman 16:d1e4b9ad3b8b 82 void edit (double * dbl, uint32_t numof_dbls) ;
JonFreeman 16:d1e4b9ad3b8b 83 double user_brake_range () ;
JonFreeman 16:d1e4b9ad3b8b 84 double top_speed () ;
JonFreeman 16:d1e4b9ad3b8b 85 double rpm2mph () ;
JonFreeman 16:d1e4b9ad3b8b 86 double rpm2mph (double) ;
JonFreeman 12:d1d21a2941ef 87 } ;
JonFreeman 12:d1d21a2941ef 88 */
JonFreeman 12:d1d21a2941ef 89
JonFreeman 16:d1e4b9ad3b8b 90 uint32_t eeprom_settings::baud () {
JonFreeman 16:d1e4b9ad3b8b 91 const uint32_t brates[] = {0, 9600, 19200, 38400, 76800, 11520};
JonFreeman 16:d1e4b9ad3b8b 92 return brates[settings[BAUD]];
JonFreeman 16:d1e4b9ad3b8b 93 }
JonFreeman 16:d1e4b9ad3b8b 94
JonFreeman 16:d1e4b9ad3b8b 95 double eeprom_settings::top_speed () {
JonFreeman 16:d1e4b9ad3b8b 96 return top_speeddbl;
JonFreeman 16:d1e4b9ad3b8b 97 }
JonFreeman 16:d1e4b9ad3b8b 98
JonFreeman 16:d1e4b9ad3b8b 99 double eeprom_settings::brake_effectiveness () {
JonFreeman 16:d1e4b9ad3b8b 100 return brake_eff;
JonFreeman 16:d1e4b9ad3b8b 101 }
JonFreeman 16:d1e4b9ad3b8b 102
JonFreeman 16:d1e4b9ad3b8b 103 double eeprom_settings::user_brake_range () {
JonFreeman 16:d1e4b9ad3b8b 104 return user_brake_rangedbl;
JonFreeman 16:d1e4b9ad3b8b 105 }
JonFreeman 16:d1e4b9ad3b8b 106
JonFreeman 16:d1e4b9ad3b8b 107 double eeprom_settings::Vnom () {
JonFreeman 16:d1e4b9ad3b8b 108 return Vnomdbl;
JonFreeman 16:d1e4b9ad3b8b 109 }
JonFreeman 16:d1e4b9ad3b8b 110
JonFreeman 16:d1e4b9ad3b8b 111 double eeprom_settings::rpm2mph () {
JonFreeman 16:d1e4b9ad3b8b 112 return rpm2mphdbl;
JonFreeman 16:d1e4b9ad3b8b 113 }
JonFreeman 16:d1e4b9ad3b8b 114
JonFreeman 16:d1e4b9ad3b8b 115 double eeprom_settings::rpm2mph (double rpm) {
JonFreeman 16:d1e4b9ad3b8b 116 return rpm2mphdbl * rpm;
JonFreeman 16:d1e4b9ad3b8b 117 }
JonFreeman 16:d1e4b9ad3b8b 118
JonFreeman 16:d1e4b9ad3b8b 119 void eeprom_settings::edit (double * dbl, uint32_t numof_dbls) {
JonFreeman 16:d1e4b9ad3b8b 120 extern void set_RCIN_offsets () ;
JonFreeman 16:d1e4b9ad3b8b 121 const char* labs[3] = {"Disabled","Uni_directional","Bi_directional"};
JonFreeman 16:d1e4b9ad3b8b 122 char temps[MAX_CLI_PARAMS+1]; // max num of parameters entered from pc terminal
JonFreeman 16:d1e4b9ad3b8b 123 uint32_t i;
JonFreeman 16:d1e4b9ad3b8b 124 double user_scratch;
JonFreeman 16:d1e4b9ad3b8b 125 double topspeed; // New Jan 2019 - set max loco speed
JonFreeman 16:d1e4b9ad3b8b 126 pc.printf ("\r\nus - User Settings data in EEPROM\r\nSyntax 'us' with no parameters lists current state.\r\n");
JonFreeman 16:d1e4b9ad3b8b 127 if (numof_dbls > 0) { // If more than 0 parameters supplied
JonFreeman 16:d1e4b9ad3b8b 128 if (numof_dbls > MAX_CLI_PARAMS)
JonFreeman 16:d1e4b9ad3b8b 129 numof_dbls = MAX_CLI_PARAMS;
JonFreeman 16:d1e4b9ad3b8b 130 for (i = 0; i < numof_dbls; i++)
JonFreeman 16:d1e4b9ad3b8b 131 temps[i] = (char)dbl[i]; // recast doubles to char
JonFreeman 16:d1e4b9ad3b8b 132 while (MAX_CLI_PARAMS > i)
JonFreeman 16:d1e4b9ad3b8b 133 temps[i++] = 0;
JonFreeman 16:d1e4b9ad3b8b 134 i = temps[0];
JonFreeman 16:d1e4b9ad3b8b 135 switch (i) { // First number read from user response after "mode"
JonFreeman 16:d1e4b9ad3b8b 136 case 11: // MotorA_dir [0 or 1], MotorB_dir [0 or 1]
JonFreeman 16:d1e4b9ad3b8b 137 wr(temps[1], MOTADIR);
JonFreeman 16:d1e4b9ad3b8b 138 wr(temps[2], MOTBDIR);
JonFreeman 16:d1e4b9ad3b8b 139 break;
JonFreeman 16:d1e4b9ad3b8b 140 case 12: // MotorA_poles [4,6,8], MotorB_poles [4,6,8]
JonFreeman 16:d1e4b9ad3b8b 141 if (temps[1] == 4 || temps[1] == 6 || temps[1] == 8)
JonFreeman 16:d1e4b9ad3b8b 142 wr(temps[1], MOTAPOLES);
JonFreeman 16:d1e4b9ad3b8b 143 if (temps[2] == 4 || temps[2] == 6 || temps[2] == 8)
JonFreeman 16:d1e4b9ad3b8b 144 wr(temps[2], MOTBPOLES);
JonFreeman 16:d1e4b9ad3b8b 145 break;
JonFreeman 16:d1e4b9ad3b8b 146 case 13: // MotorA_ current sense resistors [1 to 4], MotorB_ current sense resistors [1 to 4]
JonFreeman 16:d1e4b9ad3b8b 147 wr(temps[1], ISHUNTA); // Corrected since published
JonFreeman 16:d1e4b9ad3b8b 148 wr(temps[2], ISHUNTB);
JonFreeman 16:d1e4b9ad3b8b 149 break;
JonFreeman 16:d1e4b9ad3b8b 150 case 14:
JonFreeman 16:d1e4b9ad3b8b 151 wr(temps[1], BRAKE_EFFECTIVENESS);
JonFreeman 16:d1e4b9ad3b8b 152 break;
JonFreeman 16:d1e4b9ad3b8b 153 case 15:
JonFreeman 16:d1e4b9ad3b8b 154 pc.printf ("POT_REGBRAKE_RANGE value entered = %d\r\n", temps[1]);
JonFreeman 16:d1e4b9ad3b8b 155 if (!in_range(temps[1], POT_REGBRAKE_RANGE))
JonFreeman 16:d1e4b9ad3b8b 156 temps[1] = def(POT_REGBRAKE_RANGE);
JonFreeman 16:d1e4b9ad3b8b 157 wr (temps[1], POT_REGBRAKE_RANGE);
JonFreeman 16:d1e4b9ad3b8b 158 break;
JonFreeman 16:d1e4b9ad3b8b 159 case 16: // 2 Servo1 [0 or 1], Servo2 [0 or 1]
JonFreeman 16:d1e4b9ad3b8b 160 wr(temps[1], SVO1);
JonFreeman 16:d1e4b9ad3b8b 161 wr(temps[2], SVO2);
JonFreeman 16:d1e4b9ad3b8b 162 break;
JonFreeman 16:d1e4b9ad3b8b 163 case 17: // 3 RCIn1 [0 or 1], RCIn2 [0 or 1]
JonFreeman 16:d1e4b9ad3b8b 164 wr(temps[1], RCIN1);
JonFreeman 16:d1e4b9ad3b8b 165 wr(temps[2], RCIN2);
JonFreeman 16:d1e4b9ad3b8b 166 break;
JonFreeman 16:d1e4b9ad3b8b 167 case 18:
JonFreeman 16:d1e4b9ad3b8b 168 wr(temps[1], RCIN1REVERSE);
JonFreeman 16:d1e4b9ad3b8b 169 break;
JonFreeman 16:d1e4b9ad3b8b 170 case 19:
JonFreeman 16:d1e4b9ad3b8b 171 wr(temps[1], RCIN2REVERSE);
JonFreeman 16:d1e4b9ad3b8b 172 break;
JonFreeman 16:d1e4b9ad3b8b 173 /* case 33: // Not shown in menu, just to test stuff searching for strtod bug, to be deleted later
JonFreeman 16:d1e4b9ad3b8b 174 pc.printf ("Testing to fix strtod bug, ");
JonFreeman 16:d1e4b9ad3b8b 175 i = 0;
JonFreeman 16:d1e4b9ad3b8b 176 while (numof_dbls--)
JonFreeman 16:d1e4b9ad3b8b 177 pc.printf ("%.3f, ", dbl[i++]);
JonFreeman 16:d1e4b9ad3b8b 178 pc.printf ("TheEnd\r\n");
JonFreeman 16:d1e4b9ad3b8b 179 break;*/
JonFreeman 16:d1e4b9ad3b8b 180 case 21: // 3 RCIn1 trim [-128 to +127]
JonFreeman 16:d1e4b9ad3b8b 181 case 22: // 3 RCIn2 trim [-128 to +127]
JonFreeman 16:d1e4b9ad3b8b 182 user_scratch = dbl[1];
JonFreeman 16:d1e4b9ad3b8b 183 if (user_scratch > 127.0) user_scratch = 127.0;
JonFreeman 16:d1e4b9ad3b8b 184 if (user_scratch < -128.0) user_scratch = -128.0;
JonFreeman 16:d1e4b9ad3b8b 185 wr (((signed char) user_scratch), i == 21 ? RCI1_TRIM : RCI2_TRIM);
JonFreeman 16:d1e4b9ad3b8b 186 set_RCIN_offsets () ;
JonFreeman 16:d1e4b9ad3b8b 187 break;
JonFreeman 16:d1e4b9ad3b8b 188 case 23: // RCIN_REGBRAKE_RANGE
JonFreeman 16:d1e4b9ad3b8b 189 wr (temps[1], RCIN_REGBRAKE_RANGE);
JonFreeman 16:d1e4b9ad3b8b 190 break;
JonFreeman 16:d1e4b9ad3b8b 191 case 24: // RCIN_STICK_ATTACK
JonFreeman 16:d1e4b9ad3b8b 192 wr (temps[1], RCIN_STICK_ATTACK);
JonFreeman 16:d1e4b9ad3b8b 193 break;
JonFreeman 16:d1e4b9ad3b8b 194 case 25: // 4 Board ID '0' to '9'
JonFreeman 16:d1e4b9ad3b8b 195 if (temps[1] <= 9) // pointless to compare unsigned integer with zero
JonFreeman 16:d1e4b9ad3b8b 196 wr('0' | temps[1], BOARD_ID);
JonFreeman 16:d1e4b9ad3b8b 197 break;
JonFreeman 16:d1e4b9ad3b8b 198 case 26: // TOP_SPEED
JonFreeman 16:d1e4b9ad3b8b 199 topspeed = dbl[1];
JonFreeman 16:d1e4b9ad3b8b 200 if (topspeed > 25.0) topspeed = 25.0;
JonFreeman 16:d1e4b9ad3b8b 201 if (topspeed < 1.0) topspeed = 1.0;
JonFreeman 16:d1e4b9ad3b8b 202 wr((char)(topspeed * 10.0), TOP_SPEED);
JonFreeman 16:d1e4b9ad3b8b 203 break;
JonFreeman 16:d1e4b9ad3b8b 204 case 27: // 5 Wheel dia mm, Motor pinion teeth, Wheel gear teeth
JonFreeman 16:d1e4b9ad3b8b 205 wr(temps[1], WHEELDIA);
JonFreeman 16:d1e4b9ad3b8b 206 wr(temps[2], MOTPIN);
JonFreeman 16:d1e4b9ad3b8b 207 wr(temps[3], WHEELGEAR);
JonFreeman 16:d1e4b9ad3b8b 208 break;
JonFreeman 16:d1e4b9ad3b8b 209 case 28: // {2, 5, 2, "Command source 2= COM2 (Touch Screen), 3= Pot, 4= RC Input1, 5= RC Input2, 6=RC1+2 Robot"},
JonFreeman 16:d1e4b9ad3b8b 210 if (temps[1] > 1 && temps[1] <= 6)
JonFreeman 16:d1e4b9ad3b8b 211 wr(temps[1], COMM_SRC);
JonFreeman 16:d1e4b9ad3b8b 212 break;
JonFreeman 16:d1e4b9ad3b8b 213 case 29: // Nominal System Voltage
JonFreeman 16:d1e4b9ad3b8b 214 wr (temps[1], NOM_SYSTEM_VOLTS);
JonFreeman 16:d1e4b9ad3b8b 215 break;
JonFreeman 16:d1e4b9ad3b8b 216 case 83: // set to defaults
JonFreeman 16:d1e4b9ad3b8b 217 set_defaults ();
JonFreeman 16:d1e4b9ad3b8b 218 break;
JonFreeman 16:d1e4b9ad3b8b 219 case 30: // BAUD
JonFreeman 16:d1e4b9ad3b8b 220 wr (temps[1], BAUD);
JonFreeman 16:d1e4b9ad3b8b 221 break;
JonFreeman 16:d1e4b9ad3b8b 222 /* case 9: // 9 Save settings
JonFreeman 16:d1e4b9ad3b8b 223 save ();
JonFreeman 16:d1e4b9ad3b8b 224 pc.printf ("Saving settings to EEPROM\r\n");
JonFreeman 16:d1e4b9ad3b8b 225 break;*/
JonFreeman 16:d1e4b9ad3b8b 226 default:
JonFreeman 16:d1e4b9ad3b8b 227 pc.printf ("Not found - user setting %d\r\n", i);
JonFreeman 16:d1e4b9ad3b8b 228 i = 0;
JonFreeman 16:d1e4b9ad3b8b 229 break;
JonFreeman 16:d1e4b9ad3b8b 230 } // endof switch
JonFreeman 16:d1e4b9ad3b8b 231 if (i) {
JonFreeman 16:d1e4b9ad3b8b 232 save ();
JonFreeman 16:d1e4b9ad3b8b 233 pc.printf ("Saving settings to EEPROM\r\n");
JonFreeman 16:d1e4b9ad3b8b 234 }
JonFreeman 16:d1e4b9ad3b8b 235 } // endof // If more than 0 parameters supplied
JonFreeman 16:d1e4b9ad3b8b 236 else { // command was just "mode" on its own
JonFreeman 16:d1e4b9ad3b8b 237 pc.printf ("No Changes\r\n");
JonFreeman 16:d1e4b9ad3b8b 238 }
JonFreeman 16:d1e4b9ad3b8b 239 pc.printf ("us 11\t%s = %d, %s = %d\r\n", t(MOTADIR), settings[MOTADIR], t(MOTBDIR), settings[MOTBDIR]);
JonFreeman 16:d1e4b9ad3b8b 240 pc.printf ("us 12\t%s = %d, %s = %d\r\n", t(MOTAPOLES), settings[MOTAPOLES], t(MOTBPOLES), settings[MOTBPOLES]);
JonFreeman 16:d1e4b9ad3b8b 241 pc.printf ("us 13\tNumof motor current shunt resistors [%d to %d], MotorA = %d, MotorB = %d\r\n", min(ISHUNTA), max(ISHUNTA), settings[ISHUNTA], settings[ISHUNTB]);
JonFreeman 16:d1e4b9ad3b8b 242 pc.printf ("us 14\t%s [min %d, max %d] = %d\r\n", t(BRAKE_EFFECTIVENESS), min(BRAKE_EFFECTIVENESS), max(BRAKE_EFFECTIVENESS), settings[BRAKE_EFFECTIVENESS]);
JonFreeman 16:d1e4b9ad3b8b 243 pc.printf ("us 15\t%s[%d to %d] = %d\r\n", t(POT_REGBRAKE_RANGE), min(POT_REGBRAKE_RANGE), max(POT_REGBRAKE_RANGE), settings[POT_REGBRAKE_RANGE]);
JonFreeman 16:d1e4b9ad3b8b 244 pc.printf ("us 16\tServo1 [0 or 1] = %d %s, Servo2 [0 or 1] = %d %s\r\n", settings[SVO1], settings[SVO1] == 0 ? "Disabled":"Enabled", settings[SVO2], settings[SVO2] == 0 ? "Disabled":"Enabled");
JonFreeman 16:d1e4b9ad3b8b 245 pc.printf ("us 17\tRCIn1 [0 disable, 1 Uni_dir, 2 Bi_dir] = %d, %s\r\n\tRCIn2 [0 disable, 1 Uni_dir, 2 Bi_dir] = %d, %s\r\n", settings[RCIN1], labs[settings[RCIN1]], settings[RCIN2], labs[rd(RCIN2)]);
JonFreeman 16:d1e4b9ad3b8b 246 pc.printf ("us 18\t%s RCIN1 = %d, %s\r\n", t(RCIN1REVERSE), settings[RCIN1REVERSE], settings[RCIN1REVERSE] == 0 ? "NORMAL":"REVERSE");
JonFreeman 16:d1e4b9ad3b8b 247 pc.printf ("us 19\t%s RCIN2 = %d, %s\r\n", t(RCIN2REVERSE), settings[RCIN2REVERSE], settings[RCIN2REVERSE] == 0 ? "NORMAL":"REVERSE");
JonFreeman 16:d1e4b9ad3b8b 248 pc.printf ("us 21\tRCIn1 two's comp trim, [-128 to +127] = %d\r\n", (signed char) settings[RCI1_TRIM]);
JonFreeman 16:d1e4b9ad3b8b 249 pc.printf ("us 22\tRCIn2 two's comp trim, [-128 to +127] = %d\r\n", (signed char) settings[RCI2_TRIM]);
JonFreeman 16:d1e4b9ad3b8b 250 pc.printf ("us 23\tRCIn Regen braking uses this pcntage of movement range, [%d to %d] = %d\r\n",min(RCIN_REGBRAKE_RANGE), max(RCIN_REGBRAKE_RANGE), settings[RCIN_REGBRAKE_RANGE]);
JonFreeman 16:d1e4b9ad3b8b 251 pc.printf ("us 24\tRCIn Stick move Attack rate, [%d to %d] = %d\r\n",min(RCIN_STICK_ATTACK), max(RCIN_STICK_ATTACK), settings[RCIN_STICK_ATTACK]);
JonFreeman 16:d1e4b9ad3b8b 252 pc.printf ("us 25\tBoard ID ['0' to '9'] = '%c'\r\n", settings[BOARD_ID]);
JonFreeman 16:d1e4b9ad3b8b 253 pc.printf ("us 26\t%s = %.1f\r\n", t(TOP_SPEED), double(settings[TOP_SPEED]) / 10.0);
JonFreeman 16:d1e4b9ad3b8b 254 // WHEELDIA, MOTPIN, WHEELGEAR, used in converting RPM to MPH
JonFreeman 16:d1e4b9ad3b8b 255 pc.printf ("us 27\t%s = %d, %s = %d, %s = %d\r\n", t(WHEELDIA), settings[WHEELDIA], t(MOTPIN), settings[MOTPIN], t(WHEELGEAR), settings[WHEELGEAR]);
JonFreeman 16:d1e4b9ad3b8b 256 pc.printf ("us 28\tCommand Src [%d] - 2=COM2 (Touch Screen), 3=Pot, 4=RC In1, 5=RC In2, 6=RC1+2\r\n", settings[COMM_SRC]);
JonFreeman 16:d1e4b9ad3b8b 257 pc.printf ("us 29\t%s = %d\r\n", t(NOM_SYSTEM_VOLTS), settings[NOM_SYSTEM_VOLTS]);
JonFreeman 16:d1e4b9ad3b8b 258 pc.printf ("us 30\t%s %d\r\n", t(BAUD), settings[BAUD]);
JonFreeman 16:d1e4b9ad3b8b 259 pc.printf ("us 83\tSet to defaults\r\n");
JonFreeman 16:d1e4b9ad3b8b 260 // pc.printf ("us 9\tSave settings\r\r\n");
JonFreeman 16:d1e4b9ad3b8b 261 }
JonFreeman 16:d1e4b9ad3b8b 262
JonFreeman 16:d1e4b9ad3b8b 263 bool eeprom_settings::in_range (char val, uint32_t p) {
JonFreeman 16:d1e4b9ad3b8b 264 if ((val >= option_list[p].min) && (val <= option_list[p].max))
JonFreeman 16:d1e4b9ad3b8b 265 return true;
JonFreeman 16:d1e4b9ad3b8b 266 return false;
JonFreeman 16:d1e4b9ad3b8b 267 }
JonFreeman 16:d1e4b9ad3b8b 268 uint32_t eeprom_settings::min (uint32_t i) {
JonFreeman 16:d1e4b9ad3b8b 269 if (i >= numof_eeprom_options)
JonFreeman 16:d1e4b9ad3b8b 270 i = numof_eeprom_options - 1;
JonFreeman 16:d1e4b9ad3b8b 271 return option_list[i].min;
JonFreeman 16:d1e4b9ad3b8b 272 }
JonFreeman 16:d1e4b9ad3b8b 273 uint32_t eeprom_settings::max (uint32_t i) {
JonFreeman 16:d1e4b9ad3b8b 274 if (i >= numof_eeprom_options)
JonFreeman 16:d1e4b9ad3b8b 275 i = numof_eeprom_options - 1;
JonFreeman 16:d1e4b9ad3b8b 276 return option_list[i].max;
JonFreeman 16:d1e4b9ad3b8b 277 }
JonFreeman 16:d1e4b9ad3b8b 278 uint32_t eeprom_settings::def (uint32_t i) {
JonFreeman 16:d1e4b9ad3b8b 279 if (i >= numof_eeprom_options)
JonFreeman 16:d1e4b9ad3b8b 280 i = numof_eeprom_options - 1;
JonFreeman 16:d1e4b9ad3b8b 281 return option_list[i].de_fault;
JonFreeman 16:d1e4b9ad3b8b 282 }
JonFreeman 16:d1e4b9ad3b8b 283
JonFreeman 16:d1e4b9ad3b8b 284 const char * eeprom_settings::t (uint32_t i) {
JonFreeman 16:d1e4b9ad3b8b 285 if (i >= numof_eeprom_options)
JonFreeman 16:d1e4b9ad3b8b 286 i = numof_eeprom_options - 1;
JonFreeman 16:d1e4b9ad3b8b 287 return option_list[i].txt;
JonFreeman 16:d1e4b9ad3b8b 288 }
JonFreeman 16:d1e4b9ad3b8b 289
JonFreeman 12:d1d21a2941ef 290 bool eeprom_settings::set_defaults () { // Put default settings into EEPROM and local buffer
JonFreeman 16:d1e4b9ad3b8b 291 for (int i = 0; i < numof_eeprom_options; i++)
JonFreeman 16:d1e4b9ad3b8b 292 settings[i] = option_list[i].de_fault; // Load defaults and 'Save Settings'
JonFreeman 12:d1d21a2941ef 293 return save ();
JonFreeman 12:d1d21a2941ef 294 }
JonFreeman 12:d1d21a2941ef 295
JonFreeman 12:d1d21a2941ef 296 uint32_t eeprom_settings::errs () {
JonFreeman 12:d1d21a2941ef 297 return errors;
JonFreeman 12:d1d21a2941ef 298 }
JonFreeman 12:d1d21a2941ef 299
JonFreeman 14:acaa1add097b 300 bool eeprom_settings::do_we_have_i2c (uint32_t x) {
JonFreeman 14:acaa1add097b 301 for (int i = 0; i < i2c_device_count; i++) {
JonFreeman 14:acaa1add097b 302 if (i2c_device_list[i] == x)
JonFreeman 14:acaa1add097b 303 return true;
JonFreeman 14:acaa1add097b 304 }
JonFreeman 14:acaa1add097b 305 return false;
JonFreeman 14:acaa1add097b 306 }
JonFreeman 14:acaa1add097b 307
JonFreeman 12:d1d21a2941ef 308 // Use : eeprom_settings (SDA_PIN, SCL_PIN);
JonFreeman 12:d1d21a2941ef 309 eeprom_settings::eeprom_settings (PinName sda, PinName scl) : i2c(sda, scl) // Constructor
JonFreeman 12:d1d21a2941ef 310 {
JonFreeman 14:acaa1add097b 311 errors = i2c_device_count = 0;
JonFreeman 12:d1d21a2941ef 312 for (int i = 0; i < 36; i++)
JonFreeman 12:d1d21a2941ef 313 settings[i] = 0;
JonFreeman 16:d1e4b9ad3b8b 314 for (int i = 0; i < MAX_I2C_DEVICES; i++)
JonFreeman 14:acaa1add097b 315 i2c_device_list[i] = 0;
JonFreeman 12:d1d21a2941ef 316 i2c.frequency(400000); // Speed 400000 max.
JonFreeman 14:acaa1add097b 317 int q;
JonFreeman 12:d1d21a2941ef 318 for (int i = 0; i < 255; i += 2) { // Search for devices at all possible i2c addresses
JonFreeman 12:d1d21a2941ef 319 i2c.start();
JonFreeman 12:d1d21a2941ef 320 q = i2c.write(i); // may return error code 2 when no start issued
JonFreeman 12:d1d21a2941ef 321 switch (q) {
JonFreeman 12:d1d21a2941ef 322 case ACK:
JonFreeman 14:acaa1add097b 323 i2c_device_list[i2c_device_count++] = i;
JonFreeman 16:d1e4b9ad3b8b 324 if (i2c_device_count >= MAX_I2C_DEVICES) {
JonFreeman 16:d1e4b9ad3b8b 325 i = 300; // break out
JonFreeman 16:d1e4b9ad3b8b 326 pc.printf ("Too many i2c devices %d\r\n", i2c_device_count);
JonFreeman 16:d1e4b9ad3b8b 327 }
JonFreeman 12:d1d21a2941ef 328 case 2: // Device not seen at this address
JonFreeman 12:d1d21a2941ef 329 break;
JonFreeman 12:d1d21a2941ef 330 default:
JonFreeman 14:acaa1add097b 331 pc.printf ("Unknown error %d from i2c.write while looking for i2c devices\r\n", q);
JonFreeman 12:d1d21a2941ef 332 errors |= 512;
JonFreeman 12:d1d21a2941ef 333 break;
JonFreeman 12:d1d21a2941ef 334 }
JonFreeman 12:d1d21a2941ef 335 }
JonFreeman 12:d1d21a2941ef 336 i2c.stop();
JonFreeman 14:acaa1add097b 337 if (errors || !do_we_have_i2c(0xa0)) {
JonFreeman 12:d1d21a2941ef 338 pc.printf ("Error - EEPROM not seen %d\r\n", errors);
JonFreeman 12:d1d21a2941ef 339 errors |= 0xa0;
JonFreeman 12:d1d21a2941ef 340 ESC_Error.set (FAULT_EEPROM, errors); // Set FAULT_EEPROM bits if 24LC64 problem
JonFreeman 12:d1d21a2941ef 341 }
JonFreeman 12:d1d21a2941ef 342 else { // Found 24LC64 memory on I2C. Attempt to load settings from EEPROM
JonFreeman 12:d1d21a2941ef 343 errors = 0;
JonFreeman 12:d1d21a2941ef 344 if (!rd_24LC64 (0, settings, 32))
JonFreeman 12:d1d21a2941ef 345 ESC_Error.set (FAULT_EEPROM, 2); // Set FAULT_EEPROM bit 1 if 24LC64 problem
JonFreeman 16:d1e4b9ad3b8b 346 for (int i = 0; i < numof_eeprom_options; i++) {
JonFreeman 16:d1e4b9ad3b8b 347 if ((settings[i] < option_list[i].min) || (settings[i] > option_list[i].max)) {
JonFreeman 16:d1e4b9ad3b8b 348 pc.printf ("EEROM error with %s\r\n", option_list[i].txt);
JonFreeman 16:d1e4b9ad3b8b 349 settings[i] = option_list[i].de_fault; // Load default for faulty entry
JonFreeman 12:d1d21a2941ef 350 errors++;
JonFreeman 12:d1d21a2941ef 351 }
JonFreeman 12:d1d21a2941ef 352 }
JonFreeman 12:d1d21a2941ef 353 }
JonFreeman 12:d1d21a2941ef 354 ESC_Error.set (FAULT_EEPROM, errors); // sets nothing if 0
JonFreeman 16:d1e4b9ad3b8b 355 // if (errors > 1) { ??why > 1 ?
JonFreeman 16:d1e4b9ad3b8b 356 if (errors > 0) {
JonFreeman 16:d1e4b9ad3b8b 357 // pc.printf ("Bad settings found at startup. Restoring defaults\r\n");
JonFreeman 16:d1e4b9ad3b8b 358 // for (int i = 0; i < numof_eeprom_options2; i++)
JonFreeman 16:d1e4b9ad3b8b 359 // settings[i] = option_list[i].de_fault; // Load defaults and 'Save Settings'
JonFreeman 12:d1d21a2941ef 360 if (!wr_24LC64 (0, settings, 32)) // Save settings
JonFreeman 16:d1e4b9ad3b8b 361 pc.printf ("Error saving EEPROM in user_settings19\r\n");
JonFreeman 12:d1d21a2941ef 362 }
JonFreeman 16:d1e4b9ad3b8b 363 rpm2mphdbl = 60.0 // to Motor Revs per hour;
JonFreeman 16:d1e4b9ad3b8b 364 * ((double)settings[MOTPIN] / (double)settings[WHEELGEAR]) // Wheel revs per hour
JonFreeman 16:d1e4b9ad3b8b 365 * PI * ((double)settings[WHEELDIA] / 1000.0) // metres per hour
JonFreeman 16:d1e4b9ad3b8b 366 * 39.37 / (1760.0 * 36.0); // miles per hour
JonFreeman 16:d1e4b9ad3b8b 367 update_dbls ();
JonFreeman 16:d1e4b9ad3b8b 368 // else // 0 or 1 error max found
JonFreeman 16:d1e4b9ad3b8b 369 // pc.printf ("At startup, settings errors = %d\r\n", errors);
JonFreeman 12:d1d21a2941ef 370 } // endof constructor
JonFreeman 12:d1d21a2941ef 371
JonFreeman 16:d1e4b9ad3b8b 372 void eeprom_settings::update_dbls () {
JonFreeman 16:d1e4b9ad3b8b 373 user_brake_rangedbl = (double)settings[POT_REGBRAKE_RANGE] / 100.0;
JonFreeman 16:d1e4b9ad3b8b 374 Vnomdbl = (double)settings[NOM_SYSTEM_VOLTS];
JonFreeman 16:d1e4b9ad3b8b 375 brake_eff = (double)settings[BRAKE_EFFECTIVENESS] / 100.0;
JonFreeman 16:d1e4b9ad3b8b 376 top_speeddbl = (double)settings[TOP_SPEED] / 10.0;
JonFreeman 16:d1e4b9ad3b8b 377 }
JonFreeman 16:d1e4b9ad3b8b 378
JonFreeman 12:d1d21a2941ef 379 bool eeprom_settings::ack_poll () { // wait short while for any previous memory operation to complete
JonFreeman 0:435bf84ce48a 380 const int poll_tries = 40;
JonFreeman 0:435bf84ce48a 381 int poll_count = 0;
JonFreeman 0:435bf84ce48a 382 bool i2cfree = false;
JonFreeman 0:435bf84ce48a 383 while (poll_count++ < poll_tries && !i2cfree) {
JonFreeman 0:435bf84ce48a 384 i2c.start ();
JonFreeman 0:435bf84ce48a 385 if (i2c.write(addr_wr) == ACK)
JonFreeman 0:435bf84ce48a 386 i2cfree = true;
JonFreeman 0:435bf84ce48a 387 else
JonFreeman 17:cc9b854295d6 388 wait_us (1000); // June 2020 changed from wait_ms as now deprecated
JonFreeman 0:435bf84ce48a 389 }
JonFreeman 0:435bf84ce48a 390 return i2cfree;
JonFreeman 0:435bf84ce48a 391 }
JonFreeman 0:435bf84ce48a 392
JonFreeman 12:d1d21a2941ef 393 bool eeprom_settings::set_24LC64_internal_address (int start_addr) {
JonFreeman 0:435bf84ce48a 394 if (!ack_poll())
JonFreeman 0:435bf84ce48a 395 {
JonFreeman 0:435bf84ce48a 396 pc.printf ("Err in set_24LC64_internal_address, no ACK writing device address byte\r\n");
JonFreeman 0:435bf84ce48a 397 i2c.stop();
JonFreeman 0:435bf84ce48a 398 return false;
JonFreeman 0:435bf84ce48a 399 }
JonFreeman 0:435bf84ce48a 400 int err = 0;
JonFreeman 0:435bf84ce48a 401 if (i2c.write(start_addr >> 8) != ACK) err++;
JonFreeman 0:435bf84ce48a 402 if (i2c.write(start_addr & 0xff) != ACK) err++;
JonFreeman 0:435bf84ce48a 403 if (err) {
JonFreeman 0:435bf84ce48a 404 pc.printf ("In set_24LC64_internal_address, Believe Device present, failed in writing 2 mem addr bytes %d\r\n", err);
JonFreeman 0:435bf84ce48a 405 i2c.stop();
JonFreeman 0:435bf84ce48a 406 return false;
JonFreeman 0:435bf84ce48a 407 }
JonFreeman 0:435bf84ce48a 408 return true;
JonFreeman 0:435bf84ce48a 409 }
JonFreeman 0:435bf84ce48a 410
JonFreeman 16:d1e4b9ad3b8b 411 bool eeprom_settings::rd_24LC64 (uint32_t start_addr, char * dest, uint32_t length) {
JonFreeman 12:d1d21a2941ef 412 int acknak = ACK;
JonFreeman 12:d1d21a2941ef 413 if(length < 1)
JonFreeman 12:d1d21a2941ef 414 return false;
JonFreeman 12:d1d21a2941ef 415 if (!set_24LC64_internal_address (start_addr)) {
JonFreeman 12:d1d21a2941ef 416 pc.printf ("In rd_24LC64, failed to set_ramaddr\r\n");
JonFreeman 12:d1d21a2941ef 417 return false;
JonFreeman 12:d1d21a2941ef 418 }
JonFreeman 12:d1d21a2941ef 419 i2c.start();
JonFreeman 12:d1d21a2941ef 420 if (i2c.write(addr_rd) != ACK) {
JonFreeman 12:d1d21a2941ef 421 pc.printf ("Errors in rd_24LC64 sending addr_rd\r\n");
JonFreeman 12:d1d21a2941ef 422 return false;
JonFreeman 12:d1d21a2941ef 423 }
JonFreeman 12:d1d21a2941ef 424 while(length--) {
JonFreeman 12:d1d21a2941ef 425 if(length == 0)
JonFreeman 12:d1d21a2941ef 426 acknak = 0;
JonFreeman 12:d1d21a2941ef 427 *dest++ = i2c.read(acknak);
JonFreeman 12:d1d21a2941ef 428 }
JonFreeman 12:d1d21a2941ef 429 i2c.stop();
JonFreeman 12:d1d21a2941ef 430 return true;
JonFreeman 12:d1d21a2941ef 431 }
JonFreeman 12:d1d21a2941ef 432
JonFreeman 16:d1e4b9ad3b8b 433 bool eeprom_settings::wr_24LC64 (uint32_t start_addr, char * source, uint32_t length) {
JonFreeman 0:435bf84ce48a 434 int err = 0;
JonFreeman 0:435bf84ce48a 435 if(length < 1 || length > 32) {
JonFreeman 0:435bf84ce48a 436 pc.printf ("Length out of range %d in wr_24LC64\r\n", length);
JonFreeman 0:435bf84ce48a 437 return false;
JonFreeman 0:435bf84ce48a 438 }
JonFreeman 3:ecb00e0e8d68 439 ack_poll ();
JonFreeman 0:435bf84ce48a 440 if (!set_24LC64_internal_address (start_addr)) {
JonFreeman 0:435bf84ce48a 441 pc.printf ("In wr_24LC64, Believe Device present, failed in writing 2 mem addr bytes %d\r\n", err);
JonFreeman 0:435bf84ce48a 442 return false;
JonFreeman 0:435bf84ce48a 443 }
JonFreeman 0:435bf84ce48a 444 while(length--)
JonFreeman 0:435bf84ce48a 445 err += ACK - i2c.write(*source++);
JonFreeman 0:435bf84ce48a 446 i2c.stop();
JonFreeman 0:435bf84ce48a 447 if (err) {
JonFreeman 0:435bf84ce48a 448 pc.printf ("in wr_24LC64, device thought good, mem addr write worked, failed writing string\r\n");
JonFreeman 0:435bf84ce48a 449 return false;
JonFreeman 0:435bf84ce48a 450 }
JonFreeman 13:ef7a06fa11de 451 // pc.printf ("In wr_24LC64 No Errors Found!\r\n");
JonFreeman 0:435bf84ce48a 452 return true;
JonFreeman 0:435bf84ce48a 453 }
JonFreeman 0:435bf84ce48a 454
JonFreeman 12:d1d21a2941ef 455 char eeprom_settings::rd (uint32_t i) { // Read one setup char value from private buffer 'settings'
JonFreeman 12:d1d21a2941ef 456 if (i > 31) {
JonFreeman 16:d1e4b9ad3b8b 457 pc.printf ("ERROR Attempt to read setting %d\r\n", i);
JonFreeman 12:d1d21a2941ef 458 return 0;
JonFreeman 0:435bf84ce48a 459 }
JonFreeman 12:d1d21a2941ef 460 return settings[i];
JonFreeman 12:d1d21a2941ef 461 }
JonFreeman 12:d1d21a2941ef 462
JonFreeman 16:d1e4b9ad3b8b 463 /*
JonFreeman 16:d1e4b9ad3b8b 464 bool eeprom_settings::in_range (char val, uint32_t p) {
JonFreeman 16:d1e4b9ad3b8b 465 if ((val >= option_list[p].min) && (val <= option_list[p].max))
JonFreeman 16:d1e4b9ad3b8b 466 return true;
JonFreeman 16:d1e4b9ad3b8b 467 return false;
JonFreeman 16:d1e4b9ad3b8b 468 }
JonFreeman 16:d1e4b9ad3b8b 469 */
JonFreeman 16:d1e4b9ad3b8b 470 bool eeprom_settings::wr (char val, uint32_t p) { // Write one setup char value to private buffer 'settings'
JonFreeman 16:d1e4b9ad3b8b 471 if (p > 31)
JonFreeman 0:435bf84ce48a 472 return false;
JonFreeman 16:d1e4b9ad3b8b 473 if ((val >= min(p)) && (val <= max(p))) {
JonFreeman 16:d1e4b9ad3b8b 474 settings[p] = val;
JonFreeman 16:d1e4b9ad3b8b 475 return true;
JonFreeman 16:d1e4b9ad3b8b 476 }
JonFreeman 16:d1e4b9ad3b8b 477 settings[p] = def(p);
JonFreeman 16:d1e4b9ad3b8b 478 // pc.printf ("Wrong in wr, %s\r\n", t(p));
JonFreeman 16:d1e4b9ad3b8b 479 return false;
JonFreeman 0:435bf84ce48a 480 }
JonFreeman 0:435bf84ce48a 481
JonFreeman 12:d1d21a2941ef 482 bool eeprom_settings::save () { // Write 'settings' buffer to EEPROM
JonFreeman 16:d1e4b9ad3b8b 483 update_dbls ();
JonFreeman 12:d1d21a2941ef 484 return wr_24LC64 (0, settings, 32);
JonFreeman 0:435bf84ce48a 485 }
JonFreeman 12:d1d21a2941ef 486