Code for 'Smart Regulator' featured in 'Model Engineer', November 2020 on. Contains all work to August 2020 including all code described. Top level algorithm development is quite spares, leaving some work for you! Any questions - jon@jons-workshop.com

Dependencies:   mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM

Committer:
JonFreeman
Date:
Mon Jun 08 13:46:52 2020 +0000
Revision:
2:8e7b51353f32
Parent:
1:450090bdb6f4
Child:
3:43cb067ecd00
About to revamp i2c

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 2:8e7b51353f32 3 /*
JonFreeman 2:8e7b51353f32 4 Test 6th June 2020 - i2c sda=grey, scl=white
JonFreeman 2:8e7b51353f32 5 */
JonFreeman 2:8e7b51353f32 6 float dpd = 0.0;
JonFreeman 2:8e7b51353f32 7 /*
JonFreeman 2:8e7b51353f32 8 * May 2020 NOTE input circuit to analogue in driver pot zeners input to 3v6, then pot reduces by about 1/3.
JonFreeman 2:8e7b51353f32 9 * This makes input reading only about 0.0 to 0.66
JonFreeman 2:8e7b51353f32 10 * Temp bodge, mult by 1.5
JonFreeman 2:8e7b51353f32 11 */
JonFreeman 0:77803b3ee157 12
JonFreeman 0:77803b3ee157 13 /*
JonFreeman 0:77803b3ee157 14 Alternator Regulator
JonFreeman 0:77803b3ee157 15 Jon Freeman
JonFreeman 1:450090bdb6f4 16 June 2019 - Feb 2020
JonFreeman 1:450090bdb6f4 17
JonFreeman 1:450090bdb6f4 18 ** Prototype built using Nucleo L432KC. Final design likely to use F401RE. Code should compile for either. **
JonFreeman 0:77803b3ee157 19
JonFreeman 1:450090bdb6f4 20 ** main loop frequency upped from 32Hz to 100Hz **
JonFreeman 1:450090bdb6f4 21
JonFreeman 1:450090bdb6f4 22 WHAT THIS PROGRAMME DOES - Controls 4 stroke petrol engine driving vehicle alternator with new custom regulator
JonFreeman 1:450090bdb6f4 23
JonFreeman 1:450090bdb6f4 24 Electronics powered by higher voltage of small 12v backup battery, or alternator field output supply
JonFreeman 1:450090bdb6f4 25 Note only Field+ and MAX5035 supplied thus, all else powered from MAX outputs.
JonFreeman 1:450090bdb6f4 26 Starting engine provides rectified tickle from magneto to enable MAX5035 creating +5 and +3v3 supplies.
JonFreeman 1:450090bdb6f4 27 Alternative, selected by jumper pposition, is external switch - battery+ to MAX enable circuit.
JonFreeman 2:8e7b51353f32 28 Anytime engine revs measured < TICKOVER_RPM (or some such) RPM, field current OFF (by pwm 0)
JonFreeman 0:77803b3ee157 29
JonFreeman 0:77803b3ee157 30 BEGIN
JonFreeman 1:450090bdb6f4 31 Loop forever at 100 Hz {
JonFreeman 1:450090bdb6f4 32 Read engine RPM by monitoring engine tacho signal present on engine On/Off switch line
JonFreeman 1:450090bdb6f4 33 Adjust Alternator field current max limit according to RPM (analogue regulator limits output voltage)
JonFreeman 0:77803b3ee157 34 Measure system voltage (just in case this is ever useful)
JonFreeman 0:77803b3ee157 35 Respond to any commands arriving at serial port (setup and test link to laptop)
JonFreeman 0:77803b3ee157 36 Flash LED at 8 Hz as proof of life
JonFreeman 0:77803b3ee157 37 }
JonFreeman 0:77803b3ee157 38 END
JonFreeman 0:77803b3ee157 39
JonFreeman 0:77803b3ee157 40 INPUTS AnalogIn x 2 - Ammeter chip - current and offset AnalogIns
JonFreeman 0:77803b3ee157 41 INPUT AnalogIn - System voltage for info only.
JonFreeman 0:77803b3ee157 42 INPUT AnalogIn - ExtRevDemand
JonFreeman 0:77803b3ee157 43 INPUT AnalogIn - DriverPot
JonFreeman 0:77803b3ee157 44 INPUT Pulse engine speed indicator, speed checked against EEPROM data to select max pwm duty ratio for this speed
JonFreeman 0:77803b3ee157 45 INPUT Final pwm gate drive wired back to InterruptIn ** MAYBE USEFUL OR NOT ** Could read this back via serial to laptop
JonFreeman 0:77803b3ee157 46 OUTPUT pwm to MCP1630. This is clock to pwm chip. Also limits max duty ratio
JonFreeman 0:77803b3ee157 47 RS232 serial via USB to setup eeprom data
JonFreeman 0:77803b3ee157 48 */
JonFreeman 1:450090bdb6f4 49 // Uses software bit banged I2C - DONE (because no attempt to get I2C working on these small boards has ever worked)
JonFreeman 0:77803b3ee157 50
JonFreeman 0:77803b3ee157 51 /**
JonFreeman 0:77803b3ee157 52 * Jumpers fitted to small mbed Nucleo boards - D5 - A5 and D4 - A4 CHECK - yes
JonFreeman 0:77803b3ee157 53 */
JonFreeman 1:450090bdb6f4 54 //#ifdef TARGET_NUCLEO_F303K8 // Code too large to fit
JonFreeman 1:450090bdb6f4 55 #ifdef TARGET_NUCLEO_L432KC //
JonFreeman 0:77803b3ee157 56 /*
JonFreeman 0:77803b3ee157 57 declared in file i2c_bit_banged.cpp
JonFreeman 0:77803b3ee157 58 DigitalInOut SDA (D4); // Horrible bodge to get i2c working using bit banging.
JonFreeman 0:77803b3ee157 59 DigitalInOut SCL (D5); // DigitalInOut do not work as you might expect. Fine if used only as OpenDrain opuputs though!
JonFreeman 0:77803b3ee157 60 DigitalIn SDA_IN (A4); // That means paralleling up with two other pins as inputs
JonFreeman 0:77803b3ee157 61 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 62 */
JonFreeman 0:77803b3ee157 63 Serial pc (USBTX, USBRX); // Comms port to pc or terminal using USB lead
JonFreeman 2:8e7b51353f32 64
JonFreeman 2:8e7b51353f32 65
JonFreeman 2:8e7b51353f32 66 //BufferedSerial LocalCom (PA_9, PA_10); // New March 2019 - Taken out for i2c test 6/6/2020
JonFreeman 2:8e7b51353f32 67
JonFreeman 2:8e7b51353f32 68
JonFreeman 0:77803b3ee157 69 // Above combo of Serial and BufferedSerial is the only one to work !
JonFreeman 0:77803b3ee157 70
JonFreeman 0:77803b3ee157 71 // INPUTS :
JonFreeman 1:450090bdb6f4 72 AnalogIn Ain_SystemVolts (A6); // Sniff of alternator output, not used in control loop as done using analogue MCP1630
JonFreeman 2:8e7b51353f32 73 //AnalogIn Ammeter_In (A1); // Output of ASC709LLFTR ammeter chip (pin 20), used to increase engine revs if need be
JonFreeman 2:8e7b51353f32 74 //AnalogIn Ammeter_Ref (A0); // Ref output from ASC709LLFTR used to set ammeter zero (pin 25)
JonFreeman 1:450090bdb6f4 75
JonFreeman 1:450090bdb6f4 76 // Nov 2019. Not convinced Ext_Rev_Demand is useful
JonFreeman 2:8e7b51353f32 77 //AnalogIn Ext_Rev_Demand (D3); // Servo determines engine revs, servo out to be higher of Ext_Rev_Demand and internal calc
JonFreeman 1:450090bdb6f4 78
JonFreeman 0:77803b3ee157 79 AnalogIn Driver_Pot (A3); // If whole control system can be made to fit
JonFreeman 0:77803b3ee157 80
JonFreeman 0:77803b3ee157 81 /*
JonFreeman 0:77803b3ee157 82 MODULE PIN USAGE
JonFreeman 0:77803b3ee157 83 1 PA_9 D1 LocalCom Tx
JonFreeman 0:77803b3ee157 84 2 PA_10 D0 LocalCom Rx
JonFreeman 0:77803b3ee157 85 3 NRST
JonFreeman 0:77803b3ee157 86 4 GND
JonFreeman 1:450090bdb6f4 87 5 PA12_D2 NEW June 2019 - Output engine tacho cleaned-up, brought out to testpoint 4
JonFreeman 0:77803b3ee157 88 6 PB_0 D3 AnalogIn Ext_Rev_Demand
JonFreeman 0:77803b3ee157 89 7 PB_7 D4 SDA i2c to 24LC memory
JonFreeman 0:77803b3ee157 90 8 PB_6 D5 SCL i2c to 24LC memory
JonFreeman 0:77803b3ee157 91 9 PB_12 D6 PwmOut PWM_OSC_IN Timebase for pwm, also determines max duty ratio
JonFreeman 0:77803b3ee157 92 10 N.C.
JonFreeman 0:77803b3ee157 93 11 N.C.
JonFreeman 1:450090bdb6f4 94 12 PA_8 D9 InterruptIn pulse_tacho from engine magneto, used to measure rpm
JonFreeman 1:450090bdb6f4 95 13 PA_11 D10 Throttle servo
JonFreeman 1:450090bdb6f4 96 14 PB_5 D11 // InterruptIn VEXT PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 1:450090bdb6f4 97 15 PB_4 D12 Scope_probe
JonFreeman 0:77803b3ee157 98 16 PB_3 D13 LED Onboard LED
JonFreeman 0:77803b3ee157 99 17 3V3
JonFreeman 0:77803b3ee157 100 18 AREF
JonFreeman 1:450090bdb6f4 101 19 PA_0 A0 AnalogIn Ammeter_Ref
JonFreeman 0:77803b3ee157 102 20 PA_1 A1 AnalogIn Ammeter_In
JonFreeman 0:77803b3ee157 103 21 PA_3 A2 PWM analogue out
JonFreeman 1:450090bdb6f4 104 22 PA_4 A3 AnalogIn Driver_Pot
JonFreeman 0:77803b3ee157 105 23 PA_5 A4 n.c. SDA_IN paralleled to i2c pin, necessary because i2c has to be bit banged
JonFreeman 0:77803b3ee157 106 24 PA_6 A5 n.c. SCL_IN paralleled to i2c pin, necessary because i2c has to be bit banged
JonFreeman 1:450090bdb6f4 107 25 PA_7 A6 AnalogIn V_Sample system link voltage
JonFreeman 1:450090bdb6f4 108 26 PA_2 A7 Not used
JonFreeman 0:77803b3ee157 109 27 5V
JonFreeman 0:77803b3ee157 110 28 NRST
JonFreeman 0:77803b3ee157 111 29 GND
JonFreeman 0:77803b3ee157 112 30 VIN
JonFreeman 0:77803b3ee157 113 */
JonFreeman 0:77803b3ee157 114
JonFreeman 2:8e7b51353f32 115 // Test 6/6/2020 to get i2c working
JonFreeman 2:8e7b51353f32 116 //I2C i2c (D0, D1); // For 24LC64 eeprom
JonFreeman 2:8e7b51353f32 117 //I2C i2c (D0, D1); // For 24LC64 eeprom
JonFreeman 2:8e7b51353f32 118
JonFreeman 2:8e7b51353f32 119 I2C i2c (D0, D1); // For 24LC64 eeprom
JonFreeman 2:8e7b51353f32 120 //I2C i2c (D1, D0); // For 24LC64 eeprom DEFINITELY WRONG
JonFreeman 2:8e7b51353f32 121 // Test 6/6/2020 to get i2c working
JonFreeman 2:8e7b51353f32 122
JonFreeman 2:8e7b51353f32 123
JonFreeman 1:450090bdb6f4 124 InterruptIn pulse_tacho (D9); // Signal from engine magneto (clipped by I limit resistor and 3v3 zener)
JonFreeman 1:450090bdb6f4 125 InterruptIn VEXT (D2); // PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 0:77803b3ee157 126 // OUTPUTS :
JonFreeman 0:77803b3ee157 127
JonFreeman 1:450090bdb6f4 128 DigitalOut Scope_probe (D12); // Handy pin to hang scope probe onto while developing code
JonFreeman 1:450090bdb6f4 129 DigitalOut myled (LED1); // Green LED on board is PB_3 D13
JonFreeman 1:450090bdb6f4 130 PwmOut PWM_OSC_IN (A2); // Can alter prescaler can not use A5
JonFreeman 1:450090bdb6f4 131 //PwmOut A_OUT (A2); // Can alter prescaler can not use A5 PIN STOLEN BY PWM_OSC_IN
JonFreeman 1:450090bdb6f4 132 Servo Throttle (D10); // Changed from A2, June 2019
JonFreeman 1:450090bdb6f4 133 DigitalOut EngineTachoOut (D11); // New June 2019
JonFreeman 0:77803b3ee157 134 #endif
JonFreeman 1:450090bdb6f4 135
JonFreeman 1:450090bdb6f4 136 #ifdef TARGET_NUCLEO_F401RE //
JonFreeman 1:450090bdb6f4 137 //Serial pc (USBTX, USBRX); // Comms port to pc or terminal using USB lead
JonFreeman 1:450090bdb6f4 138 BufferedSerial pc (PA_2, PA_3, 2048, 4, NULL); // Pins 16, 17 tx, rx to pc via usb lead
JonFreeman 1:450090bdb6f4 139 //BufferedSerial pc (USBTX, USBRX); // Pins 16, 17 tx, rx to pc via usb lead
JonFreeman 1:450090bdb6f4 140 BufferedSerial LocalCom (PC_6, PC_7); // Pins 37, 38 tx, rx to Touch Screen Controller
JonFreeman 1:450090bdb6f4 141
JonFreeman 1:450090bdb6f4 142 // INPUTS :
JonFreeman 1:450090bdb6f4 143 AnalogIn Ain_SystemVolts (PB_1); // Sniff of alternator output, not used in control loop as done using analogue MCP1630
JonFreeman 2:8e7b51353f32 144 //AnalogIn Ammeter_In (PC_5); // Output of ASC709LLFTR ammeter chip (pin 20), used to increase engine revs if need be
JonFreeman 2:8e7b51353f32 145 //AnalogIn Ammeter_Ref (PB_0); // Ref output from ASC709LLFTR used to set ammeter zero (pin 25)
JonFreeman 2:8e7b51353f32 146 //AnalogIn Ext_Rev_Demand (PC_1); // Servo determines engine revs, servo out to be higher of Ext_Rev_Demand and internal calc
JonFreeman 1:450090bdb6f4 147 AnalogIn Driver_Pot (PC_2); // If whole control system can be made to fit
JonFreeman 1:450090bdb6f4 148
JonFreeman 1:450090bdb6f4 149 /*
JonFreeman 1:450090bdb6f4 150 MODULE PIN USAGE
JonFreeman 1:450090bdb6f4 151 */
JonFreeman 1:450090bdb6f4 152
JonFreeman 1:450090bdb6f4 153 InterruptIn pulse_tacho (PB_15); // Signal from engine magneto (clipped by I limit resistor and 3v3 zener)
JonFreeman 1:450090bdb6f4 154 InterruptIn VEXT (PC_12); // PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 1:450090bdb6f4 155 // OUTPUTS :
JonFreeman 1:450090bdb6f4 156
JonFreeman 1:450090bdb6f4 157 DigitalOut Scope_probe (PB_3); // Handy pin to hang scope probe onto while developing code
JonFreeman 1:450090bdb6f4 158 DigitalOut myled (PA_5); // Green LED on board is PA_5
JonFreeman 1:450090bdb6f4 159 //PwmOut PWM_OSC_IN (PA_10); // PA_10 is pwm1/3 Can alter prescaler can not use A5
JonFreeman 1:450090bdb6f4 160 PwmOut PWM_OSC_IN (PB_9); // PA_10 is pwm4/4 Can alter prescaler can not use A5
JonFreeman 1:450090bdb6f4 161 PwmOut A_OUT (PB_5); // PB_5 is pwm3/2 Can alter prescaler can not use A5 PIN STOLEN BY PWM_OSC_IN
JonFreeman 1:450090bdb6f4 162 Servo Throttle (PA_0); // PA_8 is pwm1/1 Changed from A2, June 2019
JonFreeman 1:450090bdb6f4 163 DigitalOut EngineTachoOut (PA_7); // New June 2019
JonFreeman 1:450090bdb6f4 164
JonFreeman 1:450090bdb6f4 165 I2C i2c (PB_7, PB_6); // Pins 58, 59 For 24LC64 eeprom
JonFreeman 1:450090bdb6f4 166 //#define SDA_PIN PB_7
JonFreeman 1:450090bdb6f4 167 //#define SCL_PIN PB_6
JonFreeman 1:450090bdb6f4 168
JonFreeman 1:450090bdb6f4 169 #endif
JonFreeman 1:450090bdb6f4 170
JonFreeman 2:8e7b51353f32 171 Timer microsecs; // 64 bit counter, rolls over in half million years
JonFreeman 0:77803b3ee157 172 Ticker loop_timer; // Device to cause periodic interrupts, used to sync iterations of main programme loop - slow
JonFreeman 0:77803b3ee157 173
JonFreeman 2:8e7b51353f32 174 //const double AMPS_CAL = 90.0;
JonFreeman 1:450090bdb6f4 175 extern eeprom_settings user_settings ;
JonFreeman 0:77803b3ee157 176 // SYSTEM CONSTANTS
JonFreeman 0:77803b3ee157 177 /* Please Do Not Alter these */
JonFreeman 1:450090bdb6f4 178 const int MAIN_LOOP_REPEAT_TIME_US = 10000; // 10000 us, with TACHO_TAB_SIZE = 100 means tacho_ticks_per_time is tacho_ticks_per_second
JonFreeman 0:77803b3ee157 179 /* End of Please Do Not Alter these */
JonFreeman 0:77803b3ee157 180 /* Global variable declarations */
JonFreeman 2:8e7b51353f32 181 uint32_t
JonFreeman 0:77803b3ee157 182 volt_reading = 0, // Global updated by interrupt driven read of Battery Volts
JonFreeman 0:77803b3ee157 183 driver_reading = 0,
JonFreeman 2:8e7b51353f32 184 // tacho_count = 0, // Global incremented on each transition of InterruptIn pulse_tacho
JonFreeman 1:450090bdb6f4 185 sys_timer100Hz = 0; // gets incremented by our Ticker ISR every MAIN_LOOP_REPEAT_TIME_US
JonFreeman 1:450090bdb6f4 186 double servo_position = 0.2; // set in speed control loop
JonFreeman 1:450090bdb6f4 187 double throttle_limit = SERVO_MAX;
JonFreeman 0:77803b3ee157 188 bool loop_flag = false; // made true in ISR_loop_timer, picked up and made false again in main programme loop
JonFreeman 1:450090bdb6f4 189 bool flag_25Hz = false; // As loop_flag but repeats 25 times per sec
JonFreeman 1:450090bdb6f4 190 bool flag_12Hz5 = false; // As loop_flag but repeats 12.5 times per sec
JonFreeman 1:450090bdb6f4 191 bool flag_1Hz = false; // As loop_flag but repeats 1 times per sec
JonFreeman 1:450090bdb6f4 192 bool query_toggle = false;
JonFreeman 0:77803b3ee157 193
JonFreeman 2:8e7b51353f32 194 bool flag_V_rd = false;
JonFreeman 2:8e7b51353f32 195 bool flag_Pot_rd = false;
JonFreeman 2:8e7b51353f32 196 //const int AMP_FILTER_FACTOR = 6;
JonFreeman 0:77803b3ee157 197
JonFreeman 0:77803b3ee157 198 /* End of Global variable declarations */
JonFreeman 0:77803b3ee157 199
JonFreeman 1:450090bdb6f4 200 //void ISR_fast_interrupt () { // here at 10 times main loop repeat rate (i.e. 1000Hz, 1.0ms)
JonFreeman 1:450090bdb6f4 201 void ISR_fast_interrupt () {
JonFreeman 1:450090bdb6f4 202 static uint32_t t = 0;
JonFreeman 1:450090bdb6f4 203 Scope_probe = 1; // To show how much time spent in interrupt handler
JonFreeman 0:77803b3ee157 204 switch (t) {
JonFreeman 0:77803b3ee157 205 case 0:
JonFreeman 2:8e7b51353f32 206 flag_V_rd = true;
JonFreeman 2:8e7b51353f32 207 // volt_reading >>= 1; // Result = Result / 2
JonFreeman 2:8e7b51353f32 208 // volt_reading += Ain_SystemVolts.read_u16 (); // Result = Result + New Reading
JonFreeman 0:77803b3ee157 209 break;
JonFreeman 2:8e7b51353f32 210 // case 1:
JonFreeman 2:8e7b51353f32 211 // raw_amp_reading = (double) Ammeter_In.read();
JonFreeman 2:8e7b51353f32 212 // break;
JonFreeman 0:77803b3ee157 213 case 2:
JonFreeman 2:8e7b51353f32 214 flag_Pot_rd = true;
JonFreeman 2:8e7b51353f32 215 // raw_amp_offset = Ammeter_Ref.read(); // Feb 2020 Not convinced this is useful
JonFreeman 0:77803b3ee157 216 break;
JonFreeman 2:8e7b51353f32 217 // case 3:
JonFreeman 2:8e7b51353f32 218 // ext_rev_req >>= 1; // Result = Result / 2
JonFreeman 2:8e7b51353f32 219 // ext_rev_req += Ext_Rev_Demand.read_u16();
JonFreeman 2:8e7b51353f32 220 // break;
JonFreeman 0:77803b3ee157 221 case 4:
JonFreeman 2:8e7b51353f32 222 // driver_reading >>= 1; // Result = Result / 2
JonFreeman 2:8e7b51353f32 223 // driver_reading += Driver_Pot.read_u16();
JonFreeman 1:450090bdb6f4 224 // break;
JonFreeman 1:450090bdb6f4 225 // case 5:
JonFreeman 0:77803b3ee157 226 loop_flag = true; // set flag to allow main programme loop to proceed
JonFreeman 1:450090bdb6f4 227 sys_timer100Hz++; // Just a handy measure of elapsed time for anything to use
JonFreeman 1:450090bdb6f4 228 if ((sys_timer100Hz & 0x03) == 0) // is now 12.5Hz, not 8
JonFreeman 1:450090bdb6f4 229 flag_25Hz = true; // flag gets set 25 times per sec. Other code may clear flag and make use of this
JonFreeman 1:450090bdb6f4 230 default:
JonFreeman 0:77803b3ee157 231 break;
JonFreeman 0:77803b3ee157 232 }
JonFreeman 0:77803b3ee157 233 t++;
JonFreeman 0:77803b3ee157 234 if (t > 9)
JonFreeman 0:77803b3ee157 235 t = 0;
JonFreeman 1:450090bdb6f4 236 Scope_probe = 0; // To show how much time spent in interrupt handler
JonFreeman 0:77803b3ee157 237 }
JonFreeman 0:77803b3ee157 238
JonFreeman 0:77803b3ee157 239
JonFreeman 0:77803b3ee157 240 // New stuff June 2019
JonFreeman 2:8e7b51353f32 241 // Decent way of measuring engine speed
JonFreeman 0:77803b3ee157 242 bool magneto_stretch = false;
JonFreeman 0:77803b3ee157 243 Timeout magneto_timo;
JonFreeman 2:8e7b51353f32 244 uint64_t magneto_times[4] = {13543,0,0,0}; // June 2019, only 2 of these used. Big non-zero prevents div0 error on first pass
JonFreeman 1:450090bdb6f4 245
JonFreeman 0:77803b3ee157 246
JonFreeman 1:450090bdb6f4 247 /**
JonFreeman 1:450090bdb6f4 248 void magneto_timeout ()
JonFreeman 1:450090bdb6f4 249 Here 5ms after magneto pulse detected
JonFreeman 1:450090bdb6f4 250 This is sufficient time for ringing to cease, not long enough to lose next pulse even at max engine revs.
JonFreeman 1:450090bdb6f4 251 Reset 'magneto_stretch' flag set and used in 'ISR_magneto_tacho'
JonFreeman 1:450090bdb6f4 252 */
JonFreeman 0:77803b3ee157 253 void magneto_timeout ()
JonFreeman 0:77803b3ee157 254 {
JonFreeman 0:77803b3ee157 255 magneto_stretch = false; // Magneto ringing finished by now, re-enable magneto pulse count
JonFreeman 1:450090bdb6f4 256 EngineTachoOut = 0; // Cleaned tacho output brought out to pin to look at with scope
JonFreeman 0:77803b3ee157 257 }
JonFreeman 0:77803b3ee157 258
JonFreeman 1:450090bdb6f4 259 /**
JonFreeman 1:450090bdb6f4 260 void ISR_magneto_tacho () ; // New June 2019
JonFreeman 1:450090bdb6f4 261 // Engine On/Off switch turns engine off by shorting ignition volts magneto to ground.
JonFreeman 1:450090bdb6f4 262 // Therefore when engine running, have pulse signal one pulse per rev (even though 4 stroke, spark delivered at 2 stroke rate)
JonFreeman 1:450090bdb6f4 263 // Pulse spacing 20ms @ 3000 RPM, 60ms @ 1000 RPM, 6ms @ 10000 RPM
JonFreeman 1:450090bdb6f4 264
JonFreeman 1:450090bdb6f4 265 Magneto signal rings, is quite unclean, therefore a cleanup strategy is needed.
JonFreeman 1:450090bdb6f4 266 Solution - On arrival at this interrupt handler,
JonFreeman 1:450090bdb6f4 267 If flag 'magneto_stretch' true, do nothing and return (to avoid multiple pulse count)
JonFreeman 1:450090bdb6f4 268 Set flag 'magneto_stretch' true;
JonFreeman 1:450090bdb6f4 269 Start timer 'magneto_timo' to cause 'magneto_timeout' interrupt in a time longer than ringing bt shorter than shortest time to next spark
JonFreeman 1:450090bdb6f4 270 Record time between most recent two sparks and set output bit for scope monitoring
JonFreeman 1:450090bdb6f4 271 */
JonFreeman 1:450090bdb6f4 272 void ISR_magneto_tacho () // This interrupt initiated by rising (or falling) edge of magneto output, (not both)
JonFreeman 0:77803b3ee157 273 {
JonFreeman 2:8e7b51353f32 274 uint64_t new_time;
JonFreeman 2:8e7b51353f32 275 if (!magneto_stretch) // May get this interrupt more than once per magneto pulse, respond to first, lock out subsequent
JonFreeman 2:8e7b51353f32 276 { // until magneto_timeout time has elapsed
JonFreeman 2:8e7b51353f32 277 magneto_stretch = true;
JonFreeman 2:8e7b51353f32 278 new_time = microsecs.read_high_resolution_us();
JonFreeman 0:77803b3ee157 279 magneto_times[0] = new_time - magneto_times[1]; // microsecs between most recent two sparks
JonFreeman 0:77803b3ee157 280 magneto_times[1] = new_time; // actual time microsecs of most recent spark
JonFreeman 0:77803b3ee157 281 magneto_timo.attach_us (&magneto_timeout, 5000); // To ignore ringing and multiple counts on magneto output, all settled within about 5ms
JonFreeman 1:450090bdb6f4 282 EngineTachoOut = 1; // Cleaned tacho output brought out to pin to look at with scope
JonFreeman 0:77803b3ee157 283 }
JonFreeman 0:77803b3ee157 284 }
JonFreeman 0:77803b3ee157 285
JonFreeman 0:77803b3ee157 286 // Endof New stuff June 2019
JonFreeman 0:77803b3ee157 287
JonFreeman 1:450090bdb6f4 288
JonFreeman 1:450090bdb6f4 289 VEXT_Data Field;
JonFreeman 1:450090bdb6f4 290
JonFreeman 1:450090bdb6f4 291
JonFreeman 0:77803b3ee157 292 void ISR_VEXT_rise () // InterruptIn interrupt service
JonFreeman 1:450090bdb6f4 293 { // Here is possible to read back how regulator has controlled pwm - may or may not be useful
JonFreeman 2:8e7b51353f32 294 uint64_t tmp = microsecs.read_high_resolution_us();
JonFreeman 1:450090bdb6f4 295 Field.measured_period = tmp - Field.t_on;
JonFreeman 1:450090bdb6f4 296 Field.t_on = tmp;
JonFreeman 1:450090bdb6f4 297 Field.rise_count++;
JonFreeman 0:77803b3ee157 298 }
JonFreeman 0:77803b3ee157 299 void ISR_VEXT_fall () // InterruptIn interrupt service
JonFreeman 0:77803b3ee157 300 {
JonFreeman 1:450090bdb6f4 301 Field.fall_count++;
JonFreeman 2:8e7b51353f32 302 Field.t_off = microsecs.read_high_resolution_us();
JonFreeman 1:450090bdb6f4 303 Field.measured_pw_us = Field.t_off - Field.t_on;
JonFreeman 0:77803b3ee157 304 }
JonFreeman 0:77803b3ee157 305 // **** End of Interrupt Service Routines ****
JonFreeman 0:77803b3ee157 306
JonFreeman 0:77803b3ee157 307
JonFreeman 0:77803b3ee157 308 /** uint32_t ReadEngineRPM ()
JonFreeman 1:450090bdb6f4 309 *
JonFreeman 1:450090bdb6f4 310 * June 2019 - Replaced count of alternator frequency by count of engine magneto pulses.
JonFreeman 1:450090bdb6f4 311 *
JonFreeman 0:77803b3ee157 312 */
JonFreeman 0:77803b3ee157 313 uint32_t ReadEngineRPM ()
JonFreeman 0:77803b3ee157 314 {
JonFreeman 2:8e7b51353f32 315 uint64_t time_since_last_spark = microsecs.read_high_resolution_us() - magneto_times[1];
JonFreeman 1:450090bdb6f4 316 if (time_since_last_spark > 250000) // if engine probably stopped, return old method RPM
JonFreeman 1:450090bdb6f4 317 return 0;
JonFreeman 1:450090bdb6f4 318 return (60000000 / magneto_times[0]); // 60 million / microsecs between two most recent sparks, eg 10,000us between sparks @ 6000 RPM
JonFreeman 0:77803b3ee157 319 }
JonFreeman 0:77803b3ee157 320
JonFreeman 1:450090bdb6f4 321 /*double Read_Ext_Rev_Req ()
JonFreeman 1:450090bdb6f4 322 {
JonFreeman 1:450090bdb6f4 323 double rv = (double) ext_rev_req;
JonFreeman 1:450090bdb6f4 324 return rv / 4096.0;
JonFreeman 1:450090bdb6f4 325 }*/
JonFreeman 1:450090bdb6f4 326
JonFreeman 1:450090bdb6f4 327 double Read_Driver_Pot ()
JonFreeman 1:450090bdb6f4 328 {
JonFreeman 1:450090bdb6f4 329 double rv = (double) driver_reading;
JonFreeman 1:450090bdb6f4 330 return rv / 4096.0;
JonFreeman 1:450090bdb6f4 331 }
JonFreeman 1:450090bdb6f4 332
JonFreeman 0:77803b3ee157 333 double Read_BatteryVolts ()
JonFreeman 0:77803b3ee157 334 {
JonFreeman 1:450090bdb6f4 335 return ((double) volt_reading) / 3282.5; // divisor fiddled to make voltage reading correct !
JonFreeman 0:77803b3ee157 336 }
JonFreeman 0:77803b3ee157 337
JonFreeman 1:450090bdb6f4 338 /**
JonFreeman 1:450090bdb6f4 339 void set_servo (double p) { // Only for test, called from cli
JonFreeman 1:450090bdb6f4 340 */
JonFreeman 0:77803b3ee157 341 void set_servo (double p) { // Only for test, called from cli
JonFreeman 0:77803b3ee157 342 Throttle = p;
JonFreeman 0:77803b3ee157 343 }
JonFreeman 0:77803b3ee157 344
JonFreeman 0:77803b3ee157 345 double normalise (double * p) {
JonFreeman 0:77803b3ee157 346 if (*p > 0.999)
JonFreeman 0:77803b3ee157 347 *p = 0.999;
JonFreeman 0:77803b3ee157 348 if (*p < 0.001)
JonFreeman 0:77803b3ee157 349 *p = 0.001;
JonFreeman 0:77803b3ee157 350 return * p;
JonFreeman 0:77803b3ee157 351 }
JonFreeman 0:77803b3ee157 352
JonFreeman 2:8e7b51353f32 353
JonFreeman 2:8e7b51353f32 354
JonFreeman 2:8e7b51353f32 355 //const double DRIVER_NEUTRAL = 0.18;
JonFreeman 2:8e7b51353f32 356 /**void throttle_setter () {
JonFreeman 2:8e7b51353f32 357 *
JonFreeman 2:8e7b51353f32 358 *
JonFreeman 2:8e7b51353f32 359 *
JonFreeman 2:8e7b51353f32 360 *
JonFreeman 2:8e7b51353f32 361 *
JonFreeman 2:8e7b51353f32 362 *
JonFreeman 1:450090bdb6f4 363 */
JonFreeman 2:8e7b51353f32 364 void throttle_setter () {
JonFreeman 2:8e7b51353f32 365 // double Driver_demand = Read_Driver_Pot();
JonFreeman 2:8e7b51353f32 366 const double local_hysterics = 0.03;
JonFreeman 2:8e7b51353f32 367 static double most_recent_throttle = 0.0;
JonFreeman 2:8e7b51353f32 368 double Driver_demand = dpd;
JonFreeman 2:8e7b51353f32 369 // pc.printf ("Pot\t%.2f \r\n", Driver_demand);
JonFreeman 2:8e7b51353f32 370 // pc.printf ("Pot\t%d\t%.3f \r\n", driver_reading, dpd); // Shown pot drives servo over full range.
JonFreeman 2:8e7b51353f32 371 if (Driver_demand < DRIVER_NEUTRAL) { // In braking or park
JonFreeman 2:8e7b51353f32 372 Throttle = 0.0;
JonFreeman 2:8e7b51353f32 373 }
JonFreeman 2:8e7b51353f32 374 else { // Driving
JonFreeman 2:8e7b51353f32 375 Driver_demand -= DRIVER_NEUTRAL;
JonFreeman 2:8e7b51353f32 376 Driver_demand /= (1.0 - DRIVER_NEUTRAL); // Re-normalise what's left
JonFreeman 2:8e7b51353f32 377 if ((most_recent_throttle - Driver_demand < -local_hysterics) || (most_recent_throttle - Driver_demand > local_hysterics)) {
JonFreeman 2:8e7b51353f32 378 Throttle = Driver_demand;
JonFreeman 2:8e7b51353f32 379 most_recent_throttle = Driver_demand;
JonFreeman 2:8e7b51353f32 380 servo_position = Driver_demand; // Copy to global for pc.printf only May 2020
JonFreeman 2:8e7b51353f32 381 }
JonFreeman 2:8e7b51353f32 382 }
JonFreeman 0:77803b3ee157 383 }
JonFreeman 0:77803b3ee157 384
JonFreeman 1:450090bdb6f4 385 /**void set_pwm (double d) { Range 0.0 to 1.0
JonFreeman 1:450090bdb6f4 386 This PWM used to limit max duty ratio of alternator field energisation.
JonFreeman 1:450090bdb6f4 387 With R25=33k and C4=100n controlling ramp input to CS pin of MCP1630 (not MCP1630V),
JonFreeman 1:450090bdb6f4 388 ramp terminates fet 'on' pulse after a max of approx 980 us.
JonFreeman 1:450090bdb6f4 389 With const int PWM_PERIOD_US = 2000 , duty ratio is thus limited to approx 50% max.
JonFreeman 1:450090bdb6f4 390 This is about right when using 12V alternator on 24V systems
JonFreeman 1:450090bdb6f4 391 A 1.225V reference (U7) is fed to the MCP1630 error amp which compares this to fed-back proportion of system voltage.
JonFreeman 1:450090bdb6f4 392 This adjusts final PWM down to zero % as needed to maintain alternator output voltage.
JonFreeman 1:450090bdb6f4 393 */
JonFreeman 1:450090bdb6f4 394 void set_pwm (double d) {
JonFreeman 2:8e7b51353f32 395 const double pwm_factor = MAX_FIELD_PWM * (double)PWM_PERIOD_US;
JonFreeman 1:450090bdb6f4 396 uint32_t i;
JonFreeman 1:450090bdb6f4 397 if (d < 0.0)
JonFreeman 1:450090bdb6f4 398 d = 0.0;
JonFreeman 1:450090bdb6f4 399 if (d > 1.0)
JonFreeman 1:450090bdb6f4 400 d = 1.0;
JonFreeman 2:8e7b51353f32 401 // i = (uint32_t)(d * (PWM_PERIOD_US / 2)); // div 2 when using 12v alternator in 24v system
JonFreeman 2:8e7b51353f32 402 i = (uint32_t)(d * pwm_factor); // div 2 when using 12v alternator in 24v system
JonFreeman 1:450090bdb6f4 403 // pc.printf ("Setting PWM to %d\r\n", i);
JonFreeman 1:450090bdb6f4 404 PWM_OSC_IN.pulsewidth_us (PWM_PERIOD_US - i); // Note PWM is inverted as MCP1630 uses inverted OSC_IN signal
JonFreeman 1:450090bdb6f4 405 }
JonFreeman 1:450090bdb6f4 406
JonFreeman 2:8e7b51353f32 407 /*void speed_control_factor_set (struct parameters & a) {
JonFreeman 1:450090bdb6f4 408 uint32_t v = (uint32_t)a.dbl[0];
JonFreeman 1:450090bdb6f4 409 if (v > 10)
JonFreeman 1:450090bdb6f4 410 speed_control_factor = v;
JonFreeman 1:450090bdb6f4 411 pc.printf ("speed_control_factor %d\r\n", speed_control_factor);
JonFreeman 2:8e7b51353f32 412 }*/
JonFreeman 1:450090bdb6f4 413
JonFreeman 1:450090bdb6f4 414 void set_throttle_limit (struct parameters & a) {
JonFreeman 1:450090bdb6f4 415 if (a.dbl[0] > 0.01 && a.dbl[0] < 1.001)
JonFreeman 1:450090bdb6f4 416 throttle_limit = a.dbl[0];
JonFreeman 1:450090bdb6f4 417 pc.printf ("throttle_limit %.2f\r\n", throttle_limit);
JonFreeman 1:450090bdb6f4 418 }
JonFreeman 1:450090bdb6f4 419
JonFreeman 1:450090bdb6f4 420 void query_system (struct parameters & a) {
JonFreeman 1:450090bdb6f4 421 query_toggle = !query_toggle;
JonFreeman 1:450090bdb6f4 422 // pc.printf ("Stuff about current state of system\r\n");
JonFreeman 1:450090bdb6f4 423 // pc.printf ("RPM=%d, servo%.2f\r\n", ReadEngineRPM (), servo_position);
JonFreeman 2:8e7b51353f32 424 // pc.printf ("RPM=%d\r\n", ReadEngineRPM ());
JonFreeman 2:8e7b51353f32 425 }
JonFreeman 2:8e7b51353f32 426
JonFreeman 2:8e7b51353f32 427 uint8_t madetab[340];
JonFreeman 2:8e7b51353f32 428 void maketable () { // Uses first 17 nums of user_settings relating to lim to be applied at 0, 500, 1000 --- 8000 RPM
JonFreeman 2:8e7b51353f32 429 double tabvals[20];
JonFreeman 2:8e7b51353f32 430 double diff, val = 0.0;
JonFreeman 2:8e7b51353f32 431 uint32_t tabptr = 0;
JonFreeman 2:8e7b51353f32 432 for (int i = 0; i < 17; i++) {
JonFreeman 2:8e7b51353f32 433 tabvals[i] = (double)user_settings.rd (i);
JonFreeman 2:8e7b51353f32 434 pc.printf ("%d\t%.0f\r\n", i*500, tabvals[i]);
JonFreeman 2:8e7b51353f32 435 }
JonFreeman 2:8e7b51353f32 436 for (int i = 1; i < 17; i++) {
JonFreeman 2:8e7b51353f32 437 diff = tabvals[i] - tabvals[i - 1];
JonFreeman 2:8e7b51353f32 438 diff /= 20.0; // 40 entries 25RPM apart per kRPM
JonFreeman 2:8e7b51353f32 439 for (int j = 0; j < 20; j++) {
JonFreeman 2:8e7b51353f32 440 // pc.printf ("%.0f\t", val);
JonFreeman 2:8e7b51353f32 441 madetab[tabptr++] = (uint8_t) val;
JonFreeman 2:8e7b51353f32 442 val += diff;
JonFreeman 2:8e7b51353f32 443 }
JonFreeman 2:8e7b51353f32 444 }
JonFreeman 2:8e7b51353f32 445 pc.printf ("\r\nEnd of table creation with tabptr = %d\r\n", tabptr);
JonFreeman 2:8e7b51353f32 446 while (tabptr < 340)
JonFreeman 2:8e7b51353f32 447 madetab[tabptr++] = (uint8_t) val;
JonFreeman 2:8e7b51353f32 448 }
JonFreeman 2:8e7b51353f32 449
JonFreeman 2:8e7b51353f32 450
JonFreeman 2:8e7b51353f32 451 /**void set_pwm_limit () { // May 2020
JonFreeman 2:8e7b51353f32 452 *
JonFreeman 2:8e7b51353f32 453 * Uses pure look up table to tailor pwm limit according to engine speed
JonFreeman 2:8e7b51353f32 454 *
JonFreeman 2:8e7b51353f32 455 *
JonFreeman 2:8e7b51353f32 456 *
JonFreeman 2:8e7b51353f32 457 *
JonFreeman 2:8e7b51353f32 458 */
JonFreeman 2:8e7b51353f32 459 void set_pwm_limit (uint32_t rpm) { // May 2020
JonFreeman 2:8e7b51353f32 460 //const uint8_t pwmtab [] = unsigned char array of percentages 0 to 99, spaced at 25RPM intervals
JonFreeman 2:8e7b51353f32 461 /*const uint8_t pwmtab [] = {
JonFreeman 2:8e7b51353f32 462 02,02,02,02,02,02,02,02, // 0 - 0175RPM // Slightly above 0 just to see signal on scope
JonFreeman 2:8e7b51353f32 463 02,02,02,02,02,02,02,02, // 0200 - 0375RPM
JonFreeman 2:8e7b51353f32 464 02,02,02,02,02,02,02,02, // 0400 - 0575RPM
JonFreeman 2:8e7b51353f32 465 02,02,02,02,02,02,02,02, // 0600 - 0775RPM
JonFreeman 2:8e7b51353f32 466 02,02,02,02,02,02,02,02, // 0800 - 0975RPM
JonFreeman 2:8e7b51353f32 467 02,02,02,02,02,02,02,02, // 1000 - 1175RPM
JonFreeman 2:8e7b51353f32 468 02,02,02,02,02,02,02,02, // 1200 - 1375RPM
JonFreeman 2:8e7b51353f32 469 02,02,02,02,02,02,02,02, // 1400 - 1575RPM
JonFreeman 2:8e7b51353f32 470 02,03,04,05,06,07, 8, 9, // 1600 - 1775RPM
JonFreeman 2:8e7b51353f32 471 10,11,12,13,14,15,16,17, // 1800 - 1975RPM
JonFreeman 2:8e7b51353f32 472 18,19,20,21,22,23,24,25, // 2000 - 2175RPM
JonFreeman 2:8e7b51353f32 473 26,27,28,29,30,31,32,33, // 2200 - 2375RPM
JonFreeman 2:8e7b51353f32 474 34,35,36,37,38,39,40,40, // 2400 - 2575RPM
JonFreeman 2:8e7b51353f32 475 41,41,41,42,42,42,43,43, // 2600 - 2775RPM
JonFreeman 2:8e7b51353f32 476 43,44,44,44,45,45,45,46, // 2800 - 2975RPM
JonFreeman 2:8e7b51353f32 477 46,46,47,47,47,48,48,48, // 3000 - 3175RPM
JonFreeman 2:8e7b51353f32 478 49,49,49,50,50,50,51,51, // 3200 - 3375RPM
JonFreeman 2:8e7b51353f32 479 52,52,52,53,53,53,54,54, // 3400 - 3575RPM
JonFreeman 2:8e7b51353f32 480 54,55,55,55,56,56,56,57, // 3600 - 3775RPM
JonFreeman 2:8e7b51353f32 481 57,57,58,58,58,59,59,59, // 3800 - 3975RPM
JonFreeman 2:8e7b51353f32 482 60,60,60,61,61,61,62,62, // 4000 - 4175RPM
JonFreeman 2:8e7b51353f32 483 62,63,63,63,64,64,64,65, // 4200 - 4375RPM
JonFreeman 2:8e7b51353f32 484 65,65,66,66,66,67,67,67, // 4400 - 4575RPM
JonFreeman 2:8e7b51353f32 485 68,68,68,69,69,69,70,70, // 4600 - 4775RPM
JonFreeman 2:8e7b51353f32 486 71,71,72,72,73,73,74,74, // 4800 - 4975RPM
JonFreeman 2:8e7b51353f32 487 75,75,76,76,77,77,78,78, // 5000 - 5175RPM
JonFreeman 2:8e7b51353f32 488 79,79,80,80,81,81,82,82, // 5200 - 5375RPM
JonFreeman 2:8e7b51353f32 489
JonFreeman 2:8e7b51353f32 490 83,83,84,84,85,85,86,86, // 5400 - 5575RPM
JonFreeman 2:8e7b51353f32 491 87,87,88,88,89,89,90,90, // 5600 - 5775RPM
JonFreeman 2:8e7b51353f32 492 91,91,92,92,93,93,94,94, // 5800 - 5975RPM
JonFreeman 2:8e7b51353f32 493 95,95,96,96,97,97,98,98, // 6000 - 6175RPM
JonFreeman 2:8e7b51353f32 494 99,99,99,99,99,99,99,99, // 6200 - 6375RPM
JonFreeman 2:8e7b51353f32 495 99,99,99,99,99,99,99,99, // 6400 - 6575RPM
JonFreeman 2:8e7b51353f32 496 99,99,99,99,99,99,99,99, // 6600 - 6775RPM
JonFreeman 2:8e7b51353f32 497 99,99,99,99,99,99,99,99, // 6800 - 6975RPM
JonFreeman 2:8e7b51353f32 498 99,99,99,99,99,99,99,99, // 7000 - 7175RPM
JonFreeman 2:8e7b51353f32 499 99,99,99,99,99,99,99,99, // 7200 - 7375RPM
JonFreeman 2:8e7b51353f32 500 99,99,99,99,99,99,99,99, // 7400 - 7575RPM
JonFreeman 2:8e7b51353f32 501 99,99,99,99,99,99,99,99, // 7600 - 7775RPM
JonFreeman 2:8e7b51353f32 502 99,99,99,99,99,99,99,99, // 7800 - 7975RPM
JonFreeman 2:8e7b51353f32 503 99,99,99,99,99,99,99,99, // 8000 - 8175RPM
JonFreeman 2:8e7b51353f32 504 } ;
JonFreeman 2:8e7b51353f32 505 */
JonFreeman 2:8e7b51353f32 506 // uint32_t rpm = ReadEngineRPM ();
JonFreeman 2:8e7b51353f32 507 static uint32_t oldpcent = 1000;
JonFreeman 2:8e7b51353f32 508 uint32_t index, pcent;
JonFreeman 2:8e7b51353f32 509 double pwm = 0.0;
JonFreeman 2:8e7b51353f32 510 if (rpm > 8000)
JonFreeman 2:8e7b51353f32 511 rpm = 8000;
JonFreeman 2:8e7b51353f32 512 index = rpm / 25; // to fit lut spacing of 25rpm intervals, turns rpm into index
JonFreeman 2:8e7b51353f32 513 // pcent = pwmtab[index];
JonFreeman 2:8e7b51353f32 514 pcent = madetab[index];
JonFreeman 2:8e7b51353f32 515 if (pcent != oldpcent) {
JonFreeman 2:8e7b51353f32 516 oldpcent = pcent;
JonFreeman 2:8e7b51353f32 517 pwm = (double)pcent;
JonFreeman 2:8e7b51353f32 518 pwm /= 99.0;
JonFreeman 2:8e7b51353f32 519 set_pwm (pwm);
JonFreeman 2:8e7b51353f32 520 }
JonFreeman 1:450090bdb6f4 521 }
JonFreeman 1:450090bdb6f4 522
JonFreeman 0:77803b3ee157 523 extern void command_line_interpreter () ; // Comms with optional pc or device using serial port through board USB socket
JonFreeman 0:77803b3ee157 524 extern bool i2c_init () ;
JonFreeman 0:77803b3ee157 525 extern int check_24LC64 () ;
JonFreeman 0:77803b3ee157 526
JonFreeman 0:77803b3ee157 527 // Programme Entry Point
JonFreeman 0:77803b3ee157 528 int main()
JonFreeman 0:77803b3ee157 529 {
JonFreeman 2:8e7b51353f32 530 const double filt = 0.2;
JonFreeman 0:77803b3ee157 531 // local variable declarations
JonFreeman 2:8e7b51353f32 532 // double revs_error;
JonFreeman 0:77803b3ee157 533
JonFreeman 1:450090bdb6f4 534 int32_t RPM_ave = 0, RPM_filt = 0, RPM_tmp;
JonFreeman 2:8e7b51353f32 535 // int32_t irevs_error;
JonFreeman 2:8e7b51353f32 536 uint32_t ticks25Hz = 0;
JonFreeman 1:450090bdb6f4 537
JonFreeman 0:77803b3ee157 538 pulse_tacho.fall (&ISR_magneto_tacho); // 1 pulse per engine rev
JonFreeman 0:77803b3ee157 539 VEXT.rise (&ISR_VEXT_rise); // Handles - MCP1630 has just turned mosfet on
JonFreeman 0:77803b3ee157 540 VEXT.fall (&ISR_VEXT_fall); // Handles - MCP1630 has just turned mosfet off
JonFreeman 0:77803b3ee157 541 microsecs.reset() ; // timer = 0
JonFreeman 0:77803b3ee157 542 microsecs.start () ; // 64 bit, counts micro seconds and times out in half million years
JonFreeman 1:450090bdb6f4 543
JonFreeman 1:450090bdb6f4 544 PWM_OSC_IN.period_us (PWM_PERIOD_US); // about 313Hz * 2
JonFreeman 1:450090bdb6f4 545 // PROBLEM using same pwm, common prescaler, can't update servo that fast, can't pwm field that slow.
JonFreeman 1:450090bdb6f4 546
JonFreeman 2:8e7b51353f32 547 set_pwm (0.02); // set_pwm(0.02) good for production. Set higher for test
JonFreeman 2:8e7b51353f32 548
JonFreeman 1:450090bdb6f4 549 #ifdef TARGET_NUCLEO_F401RE //
JonFreeman 1:450090bdb6f4 550 A_OUT.period_us (100); // pwm as analogue out
JonFreeman 0:77803b3ee157 551 A_OUT.pulsewidth_us (19);
JonFreeman 1:450090bdb6f4 552 #endif
JonFreeman 0:77803b3ee157 553 Throttle = servo_position;
JonFreeman 2:8e7b51353f32 554 // pc.printf ("\r\n\n\n\n\nAlternator Regulator 2020, Jon Freeman, SystemCoreClock=%d\r\n", SystemCoreClock);
JonFreeman 2:8e7b51353f32 555 pc.printf ("\r\n\n\n\n\nAlternator Regulator 2020, Jon Freeman\r\n");
JonFreeman 0:77803b3ee157 556 if (!i2c_init())
JonFreeman 0:77803b3ee157 557 pc.printf ("i2c bus failed init\r\n");
JonFreeman 0:77803b3ee157 558 pc.printf ("check_24LC64 returned 0x%x\r\n", check_24LC64());
JonFreeman 1:450090bdb6f4 559 user_settings.load () ; // Fetch values from eeprom, also builds table of speed -> pwm lookups
JonFreeman 1:450090bdb6f4 560 // pc.printf ("Loaded\r\n");
JonFreeman 0:77803b3ee157 561 // Setup Complete ! Can now start main control forever loop.
JonFreeman 1:450090bdb6f4 562 loop_timer.attach_us (&ISR_fast_interrupt, MAIN_LOOP_REPEAT_TIME_US / 10); // Start periodic interrupt generator 1000us at Feb 2020
JonFreeman 0:77803b3ee157 563
JonFreeman 2:8e7b51353f32 564 maketable ();
JonFreeman 2:8e7b51353f32 565
JonFreeman 0:77803b3ee157 566 //***** START OF MAIN LOOP
JonFreeman 0:77803b3ee157 567 while (1) { // Loop forever, repeats synchroised by waiting for ticker Interrupt Service Routine to set 'loop_flag' true
JonFreeman 0:77803b3ee157 568 while (!loop_flag) { // Most of the time is spent in this loop, repeatedly re-checking for commands from pc port
JonFreeman 0:77803b3ee157 569 command_line_interpreter () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true
JonFreeman 2:8e7b51353f32 570 if (flag_V_rd) {
JonFreeman 2:8e7b51353f32 571 flag_V_rd = false;
JonFreeman 2:8e7b51353f32 572 volt_reading >>= 1; // Result = Result / 2
JonFreeman 2:8e7b51353f32 573 volt_reading += Ain_SystemVolts.read_u16 (); // Result = Result + New Reading
JonFreeman 2:8e7b51353f32 574 }
JonFreeman 2:8e7b51353f32 575 if (flag_Pot_rd) {
JonFreeman 2:8e7b51353f32 576 flag_Pot_rd = false;
JonFreeman 2:8e7b51353f32 577 dpd *= (1.0 - filt);
JonFreeman 2:8e7b51353f32 578 dpd += filt * (Driver_Pot * 1.5); // Includes bodge around zener over-clipping input
JonFreeman 2:8e7b51353f32 579 driver_reading >>= 1; // Result = Result / 2
JonFreeman 2:8e7b51353f32 580 driver_reading += Driver_Pot.read_u16();
JonFreeman 2:8e7b51353f32 581 }
JonFreeman 1:450090bdb6f4 582 } // Jun 2019 pass here 100 times per sec
JonFreeman 1:450090bdb6f4 583 // BEGIN 100Hz stuff
JonFreeman 0:77803b3ee157 584 loop_flag = false; // Clear flag set by ticker interrupt handler
JonFreeman 1:450090bdb6f4 585
JonFreeman 1:450090bdb6f4 586 // Three variations on engine rpm.
JonFreeman 1:450090bdb6f4 587 RPM_tmp = ReadEngineRPM ();
JonFreeman 1:450090bdb6f4 588 RPM_ave += RPM_tmp; // Rising sum needs dividing and resetting to 0 when used
JonFreeman 1:450090bdb6f4 589 RPM_filt += RPM_tmp;
JonFreeman 1:450090bdb6f4 590 RPM_filt >>= 1;
JonFreeman 2:8e7b51353f32 591
JonFreeman 2:8e7b51353f32 592 set_pwm_limit (RPM_tmp); // according to RPM
JonFreeman 1:450090bdb6f4 593
JonFreeman 1:450090bdb6f4 594 // END 100Hz stuff
JonFreeman 1:450090bdb6f4 595 if (flag_25Hz) {
JonFreeman 1:450090bdb6f4 596 flag_25Hz = false;
JonFreeman 1:450090bdb6f4 597 // BEGIN 25Hz stuff
JonFreeman 0:77803b3ee157 598
JonFreeman 1:450090bdb6f4 599 // END 25Hz stuff
JonFreeman 1:450090bdb6f4 600 // BEGIN 12.5Hz stuff
JonFreeman 1:450090bdb6f4 601 flag_12Hz5 = !flag_12Hz5;
JonFreeman 1:450090bdb6f4 602 if (flag_12Hz5) { // Do any even stuff to be done 12.5 times per second
JonFreeman 2:8e7b51353f32 603 throttle_setter();
JonFreeman 2:8e7b51353f32 604 /*#ifdef SPEED_CONTROL_ENABLE
JonFreeman 1:450090bdb6f4 605 if (RPM_demand < TICKOVER_RPM)
JonFreeman 1:450090bdb6f4 606 servo_position = Throttle = 0.0;
JonFreeman 1:450090bdb6f4 607 else {
JonFreeman 1:450090bdb6f4 608 RPM_ave /= 8;
JonFreeman 1:450090bdb6f4 609 // irevs_error = RPM_demand - ReadEngineRPM ();
JonFreeman 1:450090bdb6f4 610 irevs_error = RPM_demand - RPM_filt;
JonFreeman 1:450090bdb6f4 611 revs_error = (double) irevs_error;
JonFreeman 1:450090bdb6f4 612 if (abs(revs_error) > 3.0) { // if speed error > 3rpm, tweak, otherwise deadband
JonFreeman 1:450090bdb6f4 613 //servo_position += (revs_error / 7500.0);
JonFreeman 1:450090bdb6f4 614 servo_position += (revs_error / speed_control_factor);
JonFreeman 1:450090bdb6f4 615 servo_position = normalise(&servo_position);
JonFreeman 1:450090bdb6f4 616 if (servo_position < 0.0 || servo_position > 1.0)
JonFreeman 1:450090bdb6f4 617 pc.printf ("servo_position error %f\r\n", servo_position);
JonFreeman 1:450090bdb6f4 618 if (servo_position > throttle_limit)
JonFreeman 1:450090bdb6f4 619 servo_position = throttle_limit;
JonFreeman 1:450090bdb6f4 620 Throttle = servo_position;
JonFreeman 1:450090bdb6f4 621 }
JonFreeman 1:450090bdb6f4 622 }
JonFreeman 1:450090bdb6f4 623 RPM_ave = 0; // Reset needed
JonFreeman 2:8e7b51353f32 624 #endif */
JonFreeman 1:450090bdb6f4 625 }
JonFreeman 1:450090bdb6f4 626 else { // Do odd 12.5 times per sec stuff
JonFreeman 1:450090bdb6f4 627 flag_12Hz5 = false;
JonFreeman 1:450090bdb6f4 628 myled = !myled;
JonFreeman 2:8e7b51353f32 629 // LocalCom.printf ("%d\r\n", volt_reading);
JonFreeman 1:450090bdb6f4 630 } // End of if(flag_12Hz5)
JonFreeman 1:450090bdb6f4 631 // END 12.5Hz stuff
JonFreeman 2:8e7b51353f32 632 ticks25Hz++; // advances @ 25Hz
JonFreeman 2:8e7b51353f32 633 if (ticks25Hz > 24) { // once per sec stuff
JonFreeman 1:450090bdb6f4 634 // BEGIN 1Hz stuff
JonFreeman 2:8e7b51353f32 635 ticks25Hz = 0;
JonFreeman 2:8e7b51353f32 636 // secs++;
JonFreeman 1:450090bdb6f4 637 if (query_toggle) {
JonFreeman 2:8e7b51353f32 638 pc.printf ("V = %.2f\tRPM = %u\tservo%.2f \r", Read_BatteryVolts(), /*amp_reading, */ReadEngineRPM (), servo_position);
JonFreeman 2:8e7b51353f32 639 // pc.printf ("\tRPM = %u (time %u seconds) \r", ReadEngineRPM (), (uint32_t)(microsecs.read_high_resolution_us() / 1000000));
JonFreeman 1:450090bdb6f4 640 }
JonFreeman 1:450090bdb6f4 641 // END 1Hz stuff
JonFreeman 0:77803b3ee157 642 } // eo once per second stuff
JonFreeman 1:450090bdb6f4 643 } // End of 100Hz stuff
JonFreeman 0:77803b3ee157 644 } // End of main programme loop
JonFreeman 0:77803b3ee157 645 } // End of main function - end of programme
JonFreeman 0:77803b3ee157 646 //***** END OF MAIN LOOP