Jon Freeman / Mbed 2 deprecated Alternator2020_06

Dependencies:   mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM

Committer:
JonFreeman
Date:
Fri Jun 28 19:32:51 2019 +0000
Revision:
0:77803b3ee157
Child:
1:450090bdb6f4
As at end June 2019

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JonFreeman 0:77803b3ee157 1 #include "mbed.h"
JonFreeman 0:77803b3ee157 2 #include "Alternator.h"
JonFreeman 0:77803b3ee157 3
JonFreeman 0:77803b3ee157 4 #define MAGNETO_SPEED // Selects engine speed input as magneto coil on engine switch line
JonFreeman 0:77803b3ee157 5 #define SPEED_CONTROL_ENABLE // Includes engine revs servo control loop
JonFreeman 0:77803b3ee157 6
JonFreeman 0:77803b3ee157 7 /*
JonFreeman 0:77803b3ee157 8 Alternator Regulator
JonFreeman 0:77803b3ee157 9 Jon Freeman
JonFreeman 0:77803b3ee157 10 June 2019
JonFreeman 0:77803b3ee157 11
JonFreeman 0:77803b3ee157 12 WHAT THIS PROGRAMME DOES -
JonFreeman 0:77803b3ee157 13
JonFreeman 0:77803b3ee157 14 BEGIN
JonFreeman 0:77803b3ee157 15 Loop forever at 32 Hz {
JonFreeman 0:77803b3ee157 16 Read engine RPM
JonFreeman 0:77803b3ee157 17 Adjust Alternator field current max limit according to RPM
JonFreeman 0:77803b3ee157 18 Measure system voltage (just in case this is ever useful)
JonFreeman 0:77803b3ee157 19 Respond to any commands arriving at serial port (setup and test link to laptop)
JonFreeman 0:77803b3ee157 20 Flash LED at 8 Hz as proof of life
JonFreeman 0:77803b3ee157 21 }
JonFreeman 0:77803b3ee157 22 END
JonFreeman 0:77803b3ee157 23
JonFreeman 0:77803b3ee157 24 INPUTS AnalogIn x 2 - Ammeter chip - current and offset AnalogIns
JonFreeman 0:77803b3ee157 25 INPUT AnalogIn - System voltage for info only.
JonFreeman 0:77803b3ee157 26 INPUT AnalogIn - ExtRevDemand
JonFreeman 0:77803b3ee157 27 INPUT AnalogIn - DriverPot
JonFreeman 0:77803b3ee157 28 INPUT Pulse engine speed indicator, speed checked against EEPROM data to select max pwm duty ratio for this speed
JonFreeman 0:77803b3ee157 29 INPUT Final pwm gate drive wired back to InterruptIn ** MAYBE USEFUL OR NOT ** Could read this back via serial to laptop
JonFreeman 0:77803b3ee157 30 OUTPUT pwm to MCP1630. This is clock to pwm chip. Also limits max duty ratio
JonFreeman 0:77803b3ee157 31 RS232 serial via USB to setup eeprom data
JonFreeman 0:77803b3ee157 32 */
JonFreeman 0:77803b3ee157 33 // Uses software bit banged I2C - DONE (because no attempt to get I2C working on these small boards)
JonFreeman 0:77803b3ee157 34
JonFreeman 0:77803b3ee157 35 /**
JonFreeman 0:77803b3ee157 36 * Jumpers fitted to small mbed Nucleo boards - D5 - A5 and D4 - A4 CHECK - yes
JonFreeman 0:77803b3ee157 37 */
JonFreeman 0:77803b3ee157 38 /*
JonFreeman 0:77803b3ee157 39 declared in file i2c_bit_banged.cpp
JonFreeman 0:77803b3ee157 40 DigitalInOut SDA (D4); // Horrible bodge to get i2c working using bit banging.
JonFreeman 0:77803b3ee157 41 DigitalInOut SCL (D5); // DigitalInOut do not work as you might expect. Fine if used only as OpenDrain opuputs though!
JonFreeman 0:77803b3ee157 42 DigitalIn SDA_IN (A4); // That means paralleling up with two other pins as inputs
JonFreeman 0:77803b3ee157 43 DigitalIn SCL_IN (A5); // This works but is a pain. Inbuilt I2C should have worked but never does on small boards with 32 pin cpu.
JonFreeman 0:77803b3ee157 44 */
JonFreeman 0:77803b3ee157 45 Serial pc (USBTX, USBRX); // Comms port to pc or terminal using USB lead
JonFreeman 0:77803b3ee157 46 BufferedSerial LocalCom (PA_9, PA_10); // New March 2019
JonFreeman 0:77803b3ee157 47 // Above combo of Serial and BufferedSerial is the only one to work !
JonFreeman 0:77803b3ee157 48
JonFreeman 0:77803b3ee157 49 // INPUTS :
JonFreeman 0:77803b3ee157 50 AnalogIn Ain_SystemVolts (A0); // Brought out to CN8 'AN' A0. Connect 3k3 resistor from A0 to ground.
JonFreeman 0:77803b3ee157 51 AnalogIn Ammeter_In (A1); // Output of ASC709LLFTR ammeter chip (pin 20)
JonFreeman 0:77803b3ee157 52 AnalogIn Ammeter_Ref (A6); // Ref output from ASC709LLFTR used to set ammeter zero (pin 25)
JonFreeman 0:77803b3ee157 53 AnalogIn Ext_Rev_Demand (D3); // Servo determines engine revs, servo out to be higher of Ext_Rev_Demand and internal calc
JonFreeman 0:77803b3ee157 54 AnalogIn Driver_Pot (A3); // If whole control system can be made to fit
JonFreeman 0:77803b3ee157 55 // Connect 33k resistor from A0 to nom 24 Volt system rail.
JonFreeman 0:77803b3ee157 56
JonFreeman 0:77803b3ee157 57 //#ifdef TARGET_NUCLEO_F303K8 //
JonFreeman 0:77803b3ee157 58 #ifdef TARGET_NUCLEO_L432KC //
JonFreeman 0:77803b3ee157 59 /*
JonFreeman 0:77803b3ee157 60 MODULE PIN USAGE
JonFreeman 0:77803b3ee157 61 1 PA_9 D1 LocalCom Tx
JonFreeman 0:77803b3ee157 62 2 PA_10 D0 LocalCom Rx
JonFreeman 0:77803b3ee157 63 3 NRST
JonFreeman 0:77803b3ee157 64 4 GND
JonFreeman 0:77803b3ee157 65 5 PA12_D2 NEW June 2019 - Output engine tacho cleaned-up
JonFreeman 0:77803b3ee157 66 6 PB_0 D3 AnalogIn Ext_Rev_Demand
JonFreeman 0:77803b3ee157 67 7 PB_7 D4 SDA i2c to 24LC memory
JonFreeman 0:77803b3ee157 68 8 PB_6 D5 SCL i2c to 24LC memory
JonFreeman 0:77803b3ee157 69 9 PB_12 D6 PwmOut PWM_OSC_IN Timebase for pwm, also determines max duty ratio
JonFreeman 0:77803b3ee157 70 10 N.C.
JonFreeman 0:77803b3ee157 71 11 N.C.
JonFreeman 0:77803b3ee157 72 12 PA_8 D9 InterruptIn pulse_tacho from alternator, used to measure rpm
JonFreeman 0:77803b3ee157 73 13 PA_11 D10
JonFreeman 0:77803b3ee157 74 14 PB_5 D11
JonFreeman 0:77803b3ee157 75 15 PB_4 D12
JonFreeman 0:77803b3ee157 76 16 PB_3 D13 LED Onboard LED
JonFreeman 0:77803b3ee157 77 17 3V3
JonFreeman 0:77803b3ee157 78 18 AREF
JonFreeman 0:77803b3ee157 79 19 PA_0 A0 AnalogIn V_Sample system link voltage
JonFreeman 0:77803b3ee157 80 20 PA_1 A1 AnalogIn Ammeter_In
JonFreeman 0:77803b3ee157 81 21 PA_3 A2 PWM analogue out
JonFreeman 0:77803b3ee157 82 22 PA_4 A3 InterruptIn VEXT PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 0:77803b3ee157 83 23 PA_5 A4 n.c. SDA_IN paralleled to i2c pin, necessary because i2c has to be bit banged
JonFreeman 0:77803b3ee157 84 24 PA_6 A5 n.c. SCL_IN paralleled to i2c pin, necessary because i2c has to be bit banged
JonFreeman 0:77803b3ee157 85 25 PA_7 A6 AnalogIn Ammeter_Ref
JonFreeman 0:77803b3ee157 86 26 PA_2 A7 UART2_TX Throttle Servo out now on D10, can not use D11, can not use D12 for these
JonFreeman 0:77803b3ee157 87 27 5V
JonFreeman 0:77803b3ee157 88 28 NRST
JonFreeman 0:77803b3ee157 89 29 GND
JonFreeman 0:77803b3ee157 90 30 VIN
JonFreeman 0:77803b3ee157 91 */
JonFreeman 0:77803b3ee157 92
JonFreeman 0:77803b3ee157 93 InterruptIn pulse_tacho (D9); // Signal from 'W' alternator terminal via low pass filter and Schmitt trigger cleanup
JonFreeman 0:77803b3ee157 94 // NOTE D7 pin was no good for this
JonFreeman 0:77803b3ee157 95 //InterruptIn VEXT (A3); // PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 0:77803b3ee157 96 InterruptIn VEXT (D11); // PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 0:77803b3ee157 97 // OUTPUTS :
JonFreeman 0:77803b3ee157 98
JonFreeman 0:77803b3ee157 99 //DigitalOut Scope_probe (D0); // Handy pin to hang scope probe onto while developing code
JonFreeman 0:77803b3ee157 100 DigitalOut myled(LED1); // Green LED on board is PB_3 D13
JonFreeman 0:77803b3ee157 101 //PwmOut PWM_OSC_IN (A6); // Can alter prescaler can not use A5
JonFreeman 0:77803b3ee157 102 PwmOut PWM_OSC_IN (D6); // Can alter prescaler can not use A5
JonFreeman 0:77803b3ee157 103 PwmOut A_OUT (A2); // Can alter prescaler can not use A5
JonFreeman 0:77803b3ee157 104 //Servo Throttle (A2); // Pin A2, PA3
JonFreeman 0:77803b3ee157 105 //Servo Throttle (A7); // Changed from A2, June 2019
JonFreeman 0:77803b3ee157 106 Servo Throttle (D10); // Changed from A2, June 2019
JonFreeman 0:77803b3ee157 107 DigitalOut EngineTachoOut (D2); // New June 2019
JonFreeman 0:77803b3ee157 108 #endif
JonFreeman 0:77803b3ee157 109 Timer microsecs;
JonFreeman 0:77803b3ee157 110 Ticker loop_timer; // Device to cause periodic interrupts, used to sync iterations of main programme loop - slow
JonFreeman 0:77803b3ee157 111
JonFreeman 0:77803b3ee157 112 extern eeprom_settings mode ;
JonFreeman 0:77803b3ee157 113 // SYSTEM CONSTANTS
JonFreeman 0:77803b3ee157 114 /* Please Do Not Alter these */
JonFreeman 0:77803b3ee157 115 const int MAIN_LOOP_REPEAT_TIME_US = 31250; // 31250 us, with TACHO_TAB_SIZE = 32 means tacho_ticks_per_time is tacho_ticks_per_second
JonFreeman 0:77803b3ee157 116 const int MAIN_LOOP_ITERATION_Hz = 1000000 / MAIN_LOOP_REPEAT_TIME_US; // = 32 Hz
JonFreeman 0:77803b3ee157 117 //const int FAST_INTERRUPT_RATE = 3125;
JonFreeman 0:77803b3ee157 118 /* End of Please Do Not Alter these */
JonFreeman 0:77803b3ee157 119 /* Global variable declarations */
JonFreeman 0:77803b3ee157 120 uint32_t //semaphore = 0,
JonFreeman 0:77803b3ee157 121 volt_reading = 0, // Global updated by interrupt driven read of Battery Volts
JonFreeman 0:77803b3ee157 122 amp_reading = 0,
JonFreeman 0:77803b3ee157 123 amp_offset = 0,
JonFreeman 0:77803b3ee157 124 ext_rev_req = 0,
JonFreeman 0:77803b3ee157 125 driver_reading = 0,
JonFreeman 0:77803b3ee157 126 tacho_count = 0, // Global incremented on each transition of InterruptIn pulse_tacho
JonFreeman 0:77803b3ee157 127 tacho_ticks_per_time = 0, // Global tacho ticks in most recent (MAIN_LOOP_REPEAT_TIME_US * TACHO_TABLE_SIZE) micro secs
JonFreeman 0:77803b3ee157 128 sys_timer32Hz = 0; // gets incremented by our Ticker ISR every MAIN_LOOP_REPEAT_TIME_US
JonFreeman 0:77803b3ee157 129 bool loop_flag = false; // made true in ISR_loop_timer, picked up and made false again in main programme loop
JonFreeman 0:77803b3ee157 130 bool flag_8Hz = false; // As loop_flag but repeats 8 times per sec
JonFreeman 0:77803b3ee157 131
JonFreeman 0:77803b3ee157 132
JonFreeman 0:77803b3ee157 133 const double scale = 0.125;
JonFreeman 0:77803b3ee157 134 const double shrink_by = 1.0 - scale;
JonFreeman 0:77803b3ee157 135 double glob_rpm;
JonFreeman 0:77803b3ee157 136
JonFreeman 0:77803b3ee157 137 /* End of Global variable declarations */
JonFreeman 0:77803b3ee157 138
JonFreeman 0:77803b3ee157 139 //void ISR_fast_interrupt () { // here at 10 times main loop repeat rate (i.e. 320Hz)
JonFreeman 0:77803b3ee157 140 void ISR_fast_interrupt () { // here at ** 25 ** times main loop repeat rate (1250us, i.e. 800Hz)
JonFreeman 0:77803b3ee157 141 static int t = 0;
JonFreeman 0:77803b3ee157 142 switch (t) {
JonFreeman 0:77803b3ee157 143 case 0:
JonFreeman 0:77803b3ee157 144 volt_reading >>= 1; // Result = Result / 2
JonFreeman 0:77803b3ee157 145 volt_reading += Ain_SystemVolts.read_u16 (); // Result = Result + New Reading
JonFreeman 0:77803b3ee157 146 break;
JonFreeman 0:77803b3ee157 147 case 1:
JonFreeman 0:77803b3ee157 148 amp_reading >>= 1; // Result = Result / 2
JonFreeman 0:77803b3ee157 149 amp_reading = Ammeter_In.read_u16();
JonFreeman 0:77803b3ee157 150 break;
JonFreeman 0:77803b3ee157 151 case 2:
JonFreeman 0:77803b3ee157 152 amp_offset >>= 1; // Result = Result / 2
JonFreeman 0:77803b3ee157 153 amp_offset = Ammeter_Ref.read_u16();
JonFreeman 0:77803b3ee157 154 break;
JonFreeman 0:77803b3ee157 155 case 3:
JonFreeman 0:77803b3ee157 156 ext_rev_req >>= 1; // Result = Result / 2
JonFreeman 0:77803b3ee157 157 ext_rev_req = Ext_Rev_Demand.read_u16();
JonFreeman 0:77803b3ee157 158 break;
JonFreeman 0:77803b3ee157 159 case 4:
JonFreeman 0:77803b3ee157 160 driver_reading >>= 1; // Result = Result / 2
JonFreeman 0:77803b3ee157 161 driver_reading = Driver_Pot.read_u16();
JonFreeman 0:77803b3ee157 162 break;
JonFreeman 0:77803b3ee157 163 case 5:
JonFreeman 0:77803b3ee157 164 // semaphore++;
JonFreeman 0:77803b3ee157 165 const int TACHO_TABLE_SIZE = MAIN_LOOP_ITERATION_Hz; // Ensures table contains exactly one seconds worth of samples
JonFreeman 0:77803b3ee157 166 static uint32_t h[TACHO_TABLE_SIZE], // circular buffer to contain list of 'tacho_count's
JonFreeman 0:77803b3ee157 167 i = 0, last_temp = 0;
JonFreeman 0:77803b3ee157 168 static double rpm_filt = 0.0;
JonFreeman 0:77803b3ee157 169 double tmp;
JonFreeman 0:77803b3ee157 170
JonFreeman 0:77803b3ee157 171 uint32_t temp = tacho_count; // Read very latest total pulse count from global tacho_count
JonFreeman 0:77803b3ee157 172 tmp = (double) (temp - last_temp);
JonFreeman 0:77803b3ee157 173 last_temp = temp;
JonFreeman 0:77803b3ee157 174 #ifdef MAGNETO_SPEED
JonFreeman 0:77803b3ee157 175 tmp *= (scale * 32.0 * 60.0); // ???? Is this including alternator poles count ??? Do we need MAGNETO_SPEED included
JonFreeman 0:77803b3ee157 176 #else
JonFreeman 0:77803b3ee157 177 tmp *= (scale * 32.0 * 60.0 / 12.0); // ???? Is this including alternator poles count ??? Do we need MAGNETO_SPEED included
JonFreeman 0:77803b3ee157 178 #endif
JonFreeman 0:77803b3ee157 179 rpm_filt *= shrink_by;
JonFreeman 0:77803b3ee157 180 rpm_filt += tmp;
JonFreeman 0:77803b3ee157 181 glob_rpm = rpm_filt;
JonFreeman 0:77803b3ee157 182
JonFreeman 0:77803b3ee157 183 tacho_ticks_per_time = temp - h[i]; // latest tacho total pulse count - oldest stored tacho total pulse count
JonFreeman 0:77803b3ee157 184 h[i] = temp; // latest overwrites oldest in table
JonFreeman 0:77803b3ee157 185 i++; // index to next table position for next time around
JonFreeman 0:77803b3ee157 186 if (i >= TACHO_TABLE_SIZE)
JonFreeman 0:77803b3ee157 187 i = 0; // circular buffer
JonFreeman 0:77803b3ee157 188 loop_flag = true; // set flag to allow main programme loop to proceed
JonFreeman 0:77803b3ee157 189 sys_timer32Hz++; // Just a handy measure of elapsed time for anything to use
JonFreeman 0:77803b3ee157 190 if ((sys_timer32Hz & 0x03) == 0)
JonFreeman 0:77803b3ee157 191 flag_8Hz = true; // flag gets set 8 times per sec. Other code may clear flag and make use of this
JonFreeman 0:77803b3ee157 192 break;
JonFreeman 0:77803b3ee157 193 }
JonFreeman 0:77803b3ee157 194 t++;
JonFreeman 0:77803b3ee157 195 if (t > 9)
JonFreeman 0:77803b3ee157 196 t = 0;
JonFreeman 0:77803b3ee157 197 }
JonFreeman 0:77803b3ee157 198
JonFreeman 0:77803b3ee157 199
JonFreeman 0:77803b3ee157 200
JonFreeman 0:77803b3ee157 201 /** void ISR_loop_timer ()
JonFreeman 0:77803b3ee157 202 * This ISR responds to Ticker interrupts at a rate of (probably) 32 times per second (check from constant declarations above)
JonFreeman 0:77803b3ee157 203 * This ISR sets global flag 'loop_flag' used to synchronise passes around main programme control loop.
JonFreeman 0:77803b3ee157 204 * Also, updates global int 'tacho_ticks_per_time' to contain total number of transitions from alternator 'W' terminal in
JonFreeman 0:77803b3ee157 205 * time period from exactly one second ago until now.
JonFreeman 0:77803b3ee157 206 * Increments global 'sys_timer32Hz', usable anywhere as general measure of elapsed time
JonFreeman 0:77803b3ee157 207 */
JonFreeman 0:77803b3ee157 208 void ISR_loop_timer () // This is Ticker Interrupt Service Routine - loop timer - MAIN_LOOP_REPEAT_TIME_US
JonFreeman 0:77803b3ee157 209 { // Jan 2019 MAIN_LOOP_REPEAT_TIME_US = 31.25 ms
JonFreeman 0:77803b3ee157 210 const int TACHO_TABLE_SIZE = MAIN_LOOP_ITERATION_Hz; // Ensures table contains exactly one seconds worth of samples
JonFreeman 0:77803b3ee157 211 static uint32_t h[TACHO_TABLE_SIZE], // circular buffer to contain list of 'tacho_count's
JonFreeman 0:77803b3ee157 212 i = 0, last_temp = 0;
JonFreeman 0:77803b3ee157 213 static double rpm_filt = 0.0;
JonFreeman 0:77803b3ee157 214 double tmp;
JonFreeman 0:77803b3ee157 215
JonFreeman 0:77803b3ee157 216 uint32_t temp = tacho_count; // Read very latest total pulse count from global tacho_count
JonFreeman 0:77803b3ee157 217 tmp = (double) (temp - last_temp);
JonFreeman 0:77803b3ee157 218 last_temp = temp;
JonFreeman 0:77803b3ee157 219 #ifdef MAGNETO_SPEED
JonFreeman 0:77803b3ee157 220 tmp *= (scale * 32.0 * 60.0); // ???? Is this including alternator poles count ??? Do we need MAGNETO_SPEED included
JonFreeman 0:77803b3ee157 221 #else
JonFreeman 0:77803b3ee157 222 tmp *= (scale * 32.0 * 60.0 / 12.0); // ???? Is this including alternator poles count ??? Do we need MAGNETO_SPEED included
JonFreeman 0:77803b3ee157 223 #endif
JonFreeman 0:77803b3ee157 224 // tmp *= (scale * 32.0 * 60.0 / 12.0);
JonFreeman 0:77803b3ee157 225 rpm_filt *= shrink_by;
JonFreeman 0:77803b3ee157 226 rpm_filt += tmp;
JonFreeman 0:77803b3ee157 227 glob_rpm = rpm_filt;
JonFreeman 0:77803b3ee157 228
JonFreeman 0:77803b3ee157 229 tacho_ticks_per_time = temp - h[i]; // latest tacho total pulse count - oldest stored tacho total pulse count
JonFreeman 0:77803b3ee157 230 h[i] = temp; // latest overwrites oldest in table
JonFreeman 0:77803b3ee157 231 i++; // index to next table position for next time around
JonFreeman 0:77803b3ee157 232 if (i >= TACHO_TABLE_SIZE)
JonFreeman 0:77803b3ee157 233 i = 0; // circular buffer
JonFreeman 0:77803b3ee157 234 loop_flag = true; // set flag to allow main programme loop to proceed
JonFreeman 0:77803b3ee157 235 sys_timer32Hz++; // Just a handy measure of elapsed time for anything to use
JonFreeman 0:77803b3ee157 236 if ((sys_timer32Hz & 0x03) == 0)
JonFreeman 0:77803b3ee157 237 flag_8Hz = true; // flag gets set 8 times per sec. Other code may clear flag and make use of this
JonFreeman 0:77803b3ee157 238 }
JonFreeman 0:77803b3ee157 239
JonFreeman 0:77803b3ee157 240
JonFreeman 0:77803b3ee157 241 // New stuff June 2019
JonFreeman 0:77803b3ee157 242 //uint32_t magneto_count = 0;
JonFreeman 0:77803b3ee157 243 #ifdef MAGNETO_SPEED
JonFreeman 0:77803b3ee157 244 bool magneto_stretch = false;
JonFreeman 0:77803b3ee157 245 Timeout magneto_timo;
JonFreeman 0:77803b3ee157 246 uint32_t magneto_times[8] = {0,0,0,0,0,0,0,0};
JonFreeman 0:77803b3ee157 247
JonFreeman 0:77803b3ee157 248 void ISR_magneto_tacho () ; // New June 2019
JonFreeman 0:77803b3ee157 249 // Engine On/Off switch turns engine off by shorting magneto to ground.
JonFreeman 0:77803b3ee157 250 // Therefore have pulse signal one pulse per rev (even tghough 4 stroke, spark delivered at 2 stroke rate)
JonFreeman 0:77803b3ee157 251 // Pulse spacing 20ms @ 3000 RPM, 60ms @ 1000 RPM, 6ms @ 10000 RPM
JonFreeman 0:77803b3ee157 252
JonFreeman 0:77803b3ee157 253 // Relies also on a timeout
JonFreeman 0:77803b3ee157 254 void magneto_timeout ()
JonFreeman 0:77803b3ee157 255 {
JonFreeman 0:77803b3ee157 256 magneto_stretch = false; // Magneto ringing finished by now, re-enable magneto pulse count
JonFreeman 0:77803b3ee157 257 EngineTachoOut = 0;
JonFreeman 0:77803b3ee157 258 }
JonFreeman 0:77803b3ee157 259
JonFreeman 0:77803b3ee157 260 void ISR_magneto_tacho () // Here rising or falling edge of magneto output, not both
JonFreeman 0:77803b3ee157 261 {
JonFreeman 0:77803b3ee157 262 if (!magneto_stretch)
JonFreeman 0:77803b3ee157 263 {
JonFreeman 0:77803b3ee157 264 uint32_t new_time = microsecs.read_us();
JonFreeman 0:77803b3ee157 265 if (new_time < magneto_times[1]) // rollover detection
JonFreeman 0:77803b3ee157 266 magneto_times[1] = 0;
JonFreeman 0:77803b3ee157 267 magneto_times[0] = new_time - magneto_times[1]; // microsecs between most recent two sparks
JonFreeman 0:77803b3ee157 268 magneto_times[1] = new_time; // actual time microsecs of most recent spark
JonFreeman 0:77803b3ee157 269 magneto_stretch = true;
JonFreeman 0:77803b3ee157 270 magneto_timo.attach_us (&magneto_timeout, 5000); // To ignore ringing and multiple counts on magneto output, all settled within about 5ms
JonFreeman 0:77803b3ee157 271 tacho_count++;
JonFreeman 0:77803b3ee157 272 EngineTachoOut = 1;
JonFreeman 0:77803b3ee157 273 }
JonFreeman 0:77803b3ee157 274 }
JonFreeman 0:77803b3ee157 275
JonFreeman 0:77803b3ee157 276 #endif
JonFreeman 0:77803b3ee157 277 // Endof New stuff June 2019
JonFreeman 0:77803b3ee157 278
JonFreeman 0:77803b3ee157 279 //uint32_t time_diff;
JonFreeman 0:77803b3ee157 280 /** void ISR_pulse_tacho ()
JonFreeman 0:77803b3ee157 281 *
JonFreeman 0:77803b3ee157 282 */
JonFreeman 0:77803b3ee157 283 void ISR_pulse_tacho () // Interrupt Service Routine - here after each lo to hi and hi to lo transition on pulse_tacho pin
JonFreeman 0:77803b3ee157 284 {
JonFreeman 0:77803b3ee157 285 // static uint64_t ustot = 0;
JonFreeman 0:77803b3ee157 286 // uint64_t new_time = microsecs.read_high_resolution_us();
JonFreeman 0:77803b3ee157 287 static uint32_t ustot = 0;
JonFreeman 0:77803b3ee157 288 uint32_t new_time = microsecs.read_us();
JonFreeman 0:77803b3ee157 289 if (new_time < ustot) // rollover detection
JonFreeman 0:77803b3ee157 290 ustot = 0;
JonFreeman 0:77803b3ee157 291 //// time_diff = (uint32_t) new_time - ustot;
JonFreeman 0:77803b3ee157 292 // time_diff = new_time - ustot; // always 0 or positive
JonFreeman 0:77803b3ee157 293 ustot = new_time;
JonFreeman 0:77803b3ee157 294 tacho_count++;
JonFreeman 0:77803b3ee157 295 }
JonFreeman 0:77803b3ee157 296
JonFreeman 0:77803b3ee157 297 uint32_t t_on = 0, t_off = 0, measured_pw_us = 0;
JonFreeman 0:77803b3ee157 298 int ver = 0, vef = 0;
JonFreeman 0:77803b3ee157 299 void ISR_VEXT_rise () // InterruptIn interrupt service
JonFreeman 0:77803b3ee157 300 { // Here is possible to read back how regulator has controlled pwm
JonFreeman 0:77803b3ee157 301 ver++;
JonFreeman 0:77803b3ee157 302 t_on = microsecs.read_us();
JonFreeman 0:77803b3ee157 303 }
JonFreeman 0:77803b3ee157 304 void ISR_VEXT_fall () // InterruptIn interrupt service
JonFreeman 0:77803b3ee157 305 {
JonFreeman 0:77803b3ee157 306 vef++;
JonFreeman 0:77803b3ee157 307 t_off = microsecs.read_us();
JonFreeman 0:77803b3ee157 308 measured_pw_us = t_off - t_on;
JonFreeman 0:77803b3ee157 309 }
JonFreeman 0:77803b3ee157 310 // **** End of Interrupt Service Routines ****
JonFreeman 0:77803b3ee157 311
JonFreeman 0:77803b3ee157 312
JonFreeman 0:77803b3ee157 313 /** uint32_t ReadEngineRPM ()
JonFreeman 0:77803b3ee157 314 * System timers arranged such that tacho_ticks_per_time contains most up to the moment count of tacho ticks per second.
JonFreeman 0:77803b3ee157 315 * This * 60 / number of alternator poles gives Revs Per Minute
JonFreeman 0:77803b3ee157 316 * Band pass filter alternator phase output - LF rolloff about 50Hz, HF rolloff about 1500Hz
JonFreeman 0:77803b3ee157 317 */
JonFreeman 0:77803b3ee157 318 uint32_t ReadEngineRPM ()
JonFreeman 0:77803b3ee157 319 {
JonFreeman 0:77803b3ee157 320 #ifdef MAGNETO_SPEED
JonFreeman 0:77803b3ee157 321 uint32_t time_since_last_spark = microsecs.read_us() - magneto_times[1];
JonFreeman 0:77803b3ee157 322 if (time_since_last_spark > 50000) // if engine probably stopped, return old method RPM
JonFreeman 0:77803b3ee157 323 return tacho_ticks_per_time * 60; // 1 pulse per rev from magneto
JonFreeman 0:77803b3ee157 324 return (60000000 / magneto_times[0]); // 60 million / microsecs between two most recent sparks
JonFreeman 0:77803b3ee157 325 #else
JonFreeman 0:77803b3ee157 326 return tacho_ticks_per_time * 60 / 12; // Numof alternator poles, 12, factored in.
JonFreeman 0:77803b3ee157 327 #endif
JonFreeman 0:77803b3ee157 328 }
JonFreeman 0:77803b3ee157 329
JonFreeman 0:77803b3ee157 330
JonFreeman 0:77803b3ee157 331 double Read_BatteryVolts ()
JonFreeman 0:77803b3ee157 332 {
JonFreeman 0:77803b3ee157 333 return (double) volt_reading / 1626.0; // divisor fiddled to make voltage reading correct !
JonFreeman 0:77803b3ee157 334 }
JonFreeman 0:77803b3ee157 335
JonFreeman 0:77803b3ee157 336 void set_servo (double p) { // Only for test, called from cli
JonFreeman 0:77803b3ee157 337 Throttle = p;
JonFreeman 0:77803b3ee157 338 }
JonFreeman 0:77803b3ee157 339
JonFreeman 0:77803b3ee157 340 double normalise (double * p) {
JonFreeman 0:77803b3ee157 341 if (*p > 0.999)
JonFreeman 0:77803b3ee157 342 *p = 0.999;
JonFreeman 0:77803b3ee157 343 if (*p < 0.001)
JonFreeman 0:77803b3ee157 344 *p = 0.001;
JonFreeman 0:77803b3ee157 345 return * p;
JonFreeman 0:77803b3ee157 346 }
JonFreeman 0:77803b3ee157 347
JonFreeman 0:77803b3ee157 348 uint32_t RPM_demand = 0; // For test, set from cli
JonFreeman 0:77803b3ee157 349 void set_RPM_demand (uint32_t d) {
JonFreeman 0:77803b3ee157 350 if (d < 10)
JonFreeman 0:77803b3ee157 351 d = 10;
JonFreeman 0:77803b3ee157 352 if (d > 5600)
JonFreeman 0:77803b3ee157 353 d = 5600;
JonFreeman 0:77803b3ee157 354 RPM_demand = d;
JonFreeman 0:77803b3ee157 355 }
JonFreeman 0:77803b3ee157 356
JonFreeman 0:77803b3ee157 357 extern void command_line_interpreter () ; // Comms with optional pc or device using serial port through board USB socket
JonFreeman 0:77803b3ee157 358 extern bool i2c_init () ;
JonFreeman 0:77803b3ee157 359 extern int check_24LC64 () ;
JonFreeman 0:77803b3ee157 360
JonFreeman 0:77803b3ee157 361 // Programme Entry Point
JonFreeman 0:77803b3ee157 362 int main()
JonFreeman 0:77803b3ee157 363 {
JonFreeman 0:77803b3ee157 364 // local variable declarations
JonFreeman 0:77803b3ee157 365 double servo_position = 0.2; // set in speed control loop
JonFreeman 0:77803b3ee157 366 double revs_error;
JonFreeman 0:77803b3ee157 367 int irevs_error;
JonFreeman 0:77803b3ee157 368 int ticks = 0;
JonFreeman 0:77803b3ee157 369 const double throttle_limit = 0.4;
JonFreeman 0:77803b3ee157 370
JonFreeman 0:77803b3ee157 371 loop_timer.attach_us (&ISR_loop_timer, MAIN_LOOP_REPEAT_TIME_US); // Start periodic interrupt generator
JonFreeman 0:77803b3ee157 372 #ifdef MAGNETO_SPEED
JonFreeman 0:77803b3ee157 373 pc.printf ("Magneto Mode\r\n");
JonFreeman 0:77803b3ee157 374 pulse_tacho.fall (&ISR_magneto_tacho); // 1 pulse per engine rev
JonFreeman 0:77803b3ee157 375 #else
JonFreeman 0:77803b3ee157 376 pc.printf ("Alternator W signal Mode\r\n");
JonFreeman 0:77803b3ee157 377 pulse_tacho.rise (&ISR_pulse_tacho); // Handles - Transition on filtered input version of alternator phase output
JonFreeman 0:77803b3ee157 378 pulse_tacho.fall (&ISR_pulse_tacho); //
JonFreeman 0:77803b3ee157 379 #endif
JonFreeman 0:77803b3ee157 380 VEXT.rise (&ISR_VEXT_rise); // Handles - MCP1630 has just turned mosfet on
JonFreeman 0:77803b3ee157 381 VEXT.fall (&ISR_VEXT_fall); // Handles - MCP1630 has just turned mosfet off
JonFreeman 0:77803b3ee157 382 microsecs.reset() ; // timer = 0
JonFreeman 0:77803b3ee157 383 microsecs.start () ; // 64 bit, counts micro seconds and times out in half million years
JonFreeman 0:77803b3ee157 384 PWM_OSC_IN.period_us (PWM_PERIOD_US); // about 313Hz
JonFreeman 0:77803b3ee157 385 PWM_OSC_IN.pulsewidth_us (9); // value is int
JonFreeman 0:77803b3ee157 386 A_OUT.period_us (100);
JonFreeman 0:77803b3ee157 387 A_OUT.pulsewidth_us (19);
JonFreeman 0:77803b3ee157 388 Throttle = servo_position;
JonFreeman 0:77803b3ee157 389 pc.printf ("\r\n\n\n\n\nAlternator Regulator 2019, Jon Freeman, SystemCoreClock=%d\r\n", SystemCoreClock);
JonFreeman 0:77803b3ee157 390 if (!i2c_init())
JonFreeman 0:77803b3ee157 391 pc.printf ("i2c bus failed init\r\n");
JonFreeman 0:77803b3ee157 392 // end of local variable declarations
JonFreeman 0:77803b3ee157 393 pc.printf ("check_24LC64 returned 0x%x\r\n", check_24LC64());
JonFreeman 0:77803b3ee157 394 mode.load () ; // Fetch values from eeprom, also builds table of speed -> pwm lookups
JonFreeman 0:77803b3ee157 395
JonFreeman 0:77803b3ee157 396 // Setup Complete ! Can now start main control forever loop.
JonFreeman 0:77803b3ee157 397
JonFreeman 0:77803b3ee157 398 //***** START OF MAIN LOOP
JonFreeman 0:77803b3ee157 399 while (1) { // Loop forever, repeats synchroised by waiting for ticker Interrupt Service Routine to set 'loop_flag' true
JonFreeman 0:77803b3ee157 400 while (!loop_flag) { // Most of the time is spent in this loop, repeatedly re-checking for commands from pc port
JonFreeman 0:77803b3ee157 401 command_line_interpreter () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true
JonFreeman 0:77803b3ee157 402 } // Jan 2019 pass here 32 times per sec
JonFreeman 0:77803b3ee157 403 loop_flag = false; // Clear flag set by ticker interrupt handler
JonFreeman 0:77803b3ee157 404 #ifdef SPEED_CONTROL_ENABLE
JonFreeman 0:77803b3ee157 405 // uint32_t RPM_demand = 0; // For test, set from cli
JonFreeman 0:77803b3ee157 406 // double servo_position = 0.0; // set in speed control loop
JonFreeman 0:77803b3ee157 407 // double revs_error;
JonFreeman 0:77803b3ee157 408
JonFreeman 0:77803b3ee157 409 // time_since_last_spark = microsecs.read_us() - magneto_times[1];
JonFreeman 0:77803b3ee157 410 irevs_error = RPM_demand - ReadEngineRPM ();
JonFreeman 0:77803b3ee157 411 revs_error = (double) irevs_error;
JonFreeman 0:77803b3ee157 412 if (RPM_demand < 3000)
JonFreeman 0:77803b3ee157 413 servo_position = Throttle = 0.0;
JonFreeman 0:77803b3ee157 414 else {
JonFreeman 0:77803b3ee157 415 servo_position += (revs_error / 75000.0);
JonFreeman 0:77803b3ee157 416 servo_position = normalise(&servo_position);
JonFreeman 0:77803b3ee157 417 if (servo_position < 0.0 || servo_position > 1.0)
JonFreeman 0:77803b3ee157 418 pc.printf ("servo_position error %f\r\n", servo_position);
JonFreeman 0:77803b3ee157 419 if (servo_position > throttle_limit)
JonFreeman 0:77803b3ee157 420 servo_position = throttle_limit;
JonFreeman 0:77803b3ee157 421 Throttle = servo_position;
JonFreeman 0:77803b3ee157 422 }
JonFreeman 0:77803b3ee157 423 #endif
JonFreeman 0:77803b3ee157 424
JonFreeman 0:77803b3ee157 425 PWM_OSC_IN.pulsewidth_us (mode.get_pwm((int)glob_rpm)); // Update field current according to latest measured RPM
JonFreeman 0:77803b3ee157 426
JonFreeman 0:77803b3ee157 427 // while (LocalCom.readable()) {
JonFreeman 0:77803b3ee157 428 // int q = LocalCom.getc();
JonFreeman 0:77803b3ee157 429 // //q++;
JonFreeman 0:77803b3ee157 430 // pc.putc (q);
JonFreeman 0:77803b3ee157 431 // }
JonFreeman 0:77803b3ee157 432
JonFreeman 0:77803b3ee157 433 if (flag_8Hz) { // Do any stuff to be done 8 times per second
JonFreeman 0:77803b3ee157 434 flag_8Hz = false;
JonFreeman 0:77803b3ee157 435 myled = !myled;
JonFreeman 0:77803b3ee157 436 LocalCom.printf ("%d\r\n", volt_reading);
JonFreeman 0:77803b3ee157 437
JonFreeman 0:77803b3ee157 438 ticks++;
JonFreeman 0:77803b3ee157 439 if (ticks > 7) { // once per sec stuff
JonFreeman 0:77803b3ee157 440 ticks = 0;
JonFreeman 0:77803b3ee157 441 pc.printf ("RPM %d, err %.1f, s_p %.2f\r\n", ReadEngineRPM (), revs_error, servo_position);
JonFreeman 0:77803b3ee157 442 } // eo once per second stuff
JonFreeman 0:77803b3ee157 443 } // End of if(flag_8Hz)
JonFreeman 0:77803b3ee157 444 } // End of main programme loop
JonFreeman 0:77803b3ee157 445 } // End of main function - end of programme
JonFreeman 0:77803b3ee157 446 //***** END OF MAIN LOOP