Jon Freeman / Mbed 2 deprecated Alternator2020_06

Dependencies:   mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM

Committer:
JonFreeman
Date:
Mon Jul 27 08:44:59 2020 +0000
Revision:
3:43cb067ecd00
Parent:
2:8e7b51353f32
Child:
4:28cc0cf01570
End of July after good day out at Ashton Court

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 3:43cb067ecd00 3 #include "BufferedSerial.h"
JonFreeman 3:43cb067ecd00 4 #include "I2CEeprom.h"
JonFreeman 3:43cb067ecd00 5 #include "LM75B.h" // New I2C temp sensor code March 2020 (to suit possible next board issue, harmless otherwise)
JonFreeman 3:43cb067ecd00 6 #include "rpm.h"
JonFreeman 3:43cb067ecd00 7 #include "field.h"
JonFreeman 3:43cb067ecd00 8 //#include "gps_mod.h"
JonFreeman 3:43cb067ecd00 9 //#include "baro.h"
JonFreeman 3:43cb067ecd00 10
JonFreeman 3:43cb067ecd00 11 #ifdef TARGET_NUCLEO_L432KC // 24LC and LM75 work
JonFreeman 3:43cb067ecd00 12 // #define SDA_PIN D0 // good
JonFreeman 3:43cb067ecd00 13 // #define SCL_PIN D1
JonFreeman 3:43cb067ecd00 14 #define SDA_PIN D4 // good
JonFreeman 3:43cb067ecd00 15 #define SCL_PIN D5
JonFreeman 3:43cb067ecd00 16 #endif
JonFreeman 3:43cb067ecd00 17
JonFreeman 3:43cb067ecd00 18 /*******************************************************************************
JonFreeman 3:43cb067ecd00 19 DON'T FORGET TO REMOVE SOLDER LINKS SB16 AND SB18 ON L432KC BOARD
JonFreeman 3:43cb067ecd00 20 *******************************************************************************/
JonFreeman 3:43cb067ecd00 21 //During test LED across field has been useful visual aid. Incorporate similar on new board.
JonFreeman 2:8e7b51353f32 22 /*
JonFreeman 2:8e7b51353f32 23 * May 2020 NOTE input circuit to analogue in driver pot zeners input to 3v6, then pot reduces by about 1/3.
JonFreeman 2:8e7b51353f32 24 * This makes input reading only about 0.0 to 0.66
JonFreeman 2:8e7b51353f32 25 * Temp bodge, mult by 1.5
JonFreeman 3:43cb067ecd00 26
JonFreeman 3:43cb067ecd00 27 * Two voltages now measured. Link voltage (alternator output), and field supply (which may come from battery when main output low)
JonFreeman 2:8e7b51353f32 28 */
JonFreeman 0:77803b3ee157 29
JonFreeman 0:77803b3ee157 30 /*
JonFreeman 0:77803b3ee157 31 Alternator Regulator
JonFreeman 0:77803b3ee157 32 Jon Freeman
JonFreeman 3:43cb067ecd00 33 June 2019 - June 2020
JonFreeman 1:450090bdb6f4 34
JonFreeman 3:43cb067ecd00 35 ** Prototype built using Nucleo L432KC. Having solved i2c problem, this looks good for final product
JonFreeman 0:77803b3ee157 36
JonFreeman 1:450090bdb6f4 37 ** main loop frequency upped from 32Hz to 100Hz **
JonFreeman 1:450090bdb6f4 38
JonFreeman 1:450090bdb6f4 39 WHAT THIS PROGRAMME DOES - Controls 4 stroke petrol engine driving vehicle alternator with new custom regulator
JonFreeman 1:450090bdb6f4 40
JonFreeman 3:43cb067ecd00 41 Electronics powered by higher voltage of small 12v backup battery, or alternator output
JonFreeman 1:450090bdb6f4 42 Note only Field+ and MAX5035 supplied thus, all else powered from MAX outputs.
JonFreeman 1:450090bdb6f4 43 Starting engine provides rectified tickle from magneto to enable MAX5035 creating +5 and +3v3 supplies.
JonFreeman 3:43cb067ecd00 44 Alternative, selected by jumper position, is external switch - battery+ to MAX enable circuit. ** Review this **
JonFreeman 3:43cb067ecd00 45 Anytime engine revs measured < TICKOVER_RPM (or some such) RPM, field current OFF (by pwm 0) , see speed related pwm limit table
JonFreeman 0:77803b3ee157 46
JonFreeman 0:77803b3ee157 47 BEGIN
JonFreeman 1:450090bdb6f4 48 Loop forever at 100 Hz {
JonFreeman 1:450090bdb6f4 49 Read engine RPM by monitoring engine tacho signal present on engine On/Off switch line
JonFreeman 1:450090bdb6f4 50 Adjust Alternator field current max limit according to RPM (analogue regulator limits output voltage)
JonFreeman 0:77803b3ee157 51 Measure system voltage (just in case this is ever useful)
JonFreeman 0:77803b3ee157 52 Respond to any commands arriving at serial port (setup and test link to laptop)
JonFreeman 0:77803b3ee157 53 Flash LED at 8 Hz as proof of life
JonFreeman 0:77803b3ee157 54 }
JonFreeman 0:77803b3ee157 55 END
JonFreeman 0:77803b3ee157 56
JonFreeman 0:77803b3ee157 57 INPUTS AnalogIn x 2 - Ammeter chip - current and offset AnalogIns
JonFreeman 0:77803b3ee157 58 INPUT AnalogIn - System voltage for info only.
JonFreeman 0:77803b3ee157 59 INPUT AnalogIn - ExtRevDemand
JonFreeman 0:77803b3ee157 60 INPUT AnalogIn - DriverPot
JonFreeman 0:77803b3ee157 61 INPUT Pulse engine speed indicator, speed checked against EEPROM data to select max pwm duty ratio for this speed
JonFreeman 0:77803b3ee157 62 INPUT Final pwm gate drive wired back to InterruptIn ** MAYBE USEFUL OR NOT ** Could read this back via serial to laptop
JonFreeman 0:77803b3ee157 63 OUTPUT pwm to MCP1630. This is clock to pwm chip. Also limits max duty ratio
JonFreeman 0:77803b3ee157 64 RS232 serial via USB to setup eeprom data
JonFreeman 0:77803b3ee157 65 */
JonFreeman 0:77803b3ee157 66
JonFreeman 0:77803b3ee157 67 /**
JonFreeman 0:77803b3ee157 68 * Jumpers fitted to small mbed Nucleo boards - D5 - A5 and D4 - A4 CHECK - yes
JonFreeman 0:77803b3ee157 69 */
JonFreeman 3:43cb067ecd00 70 //#ifdef TARGET_NUCLEO_L432KC // Has to be, quite settled now on this, having solved i2c problems
JonFreeman 3:43cb067ecd00 71 BufferedSerial pc (USBTX, USBRX, 4096, 4, NULL); // Comms port to pc or terminal using USB lead
JonFreeman 2:8e7b51353f32 72 //BufferedSerial LocalCom (PA_9, PA_10); // New March 2019 - Taken out for i2c test 6/6/2020
JonFreeman 2:8e7b51353f32 73
JonFreeman 0:77803b3ee157 74 // INPUTS :
JonFreeman 3:43cb067ecd00 75 AnalogIn Ain_Link_Volts (A6); // Sniff of alternator output, not used in control loop as done using analogue MCP1630
JonFreeman 3:43cb067ecd00 76 AnalogIn Ammeter_In (A1); // Output of ASC709LLFTR ammeter chip (pin 20), used to increase engine revs if need be
JonFreeman 2:8e7b51353f32 77 //AnalogIn Ammeter_Ref (A0); // Ref output from ASC709LLFTR used to set ammeter zero (pin 25)
JonFreeman 1:450090bdb6f4 78
JonFreeman 3:43cb067ecd00 79 // Nov 2019. Not convinced Ext_Rev_Demand is useful ** July 2020 - repurposed, voltmeter Field_Supply_V
JonFreeman 2:8e7b51353f32 80 //AnalogIn Ext_Rev_Demand (D3); // Servo determines engine revs, servo out to be higher of Ext_Rev_Demand and internal calc
JonFreeman 3:43cb067ecd00 81 AnalogIn Field_Supply_V (D3); // Servo determines engine revs, servo out to be higher of Ext_Rev_Demand and internal calc
JonFreeman 1:450090bdb6f4 82
JonFreeman 0:77803b3ee157 83 AnalogIn Driver_Pot (A3); // If whole control system can be made to fit
JonFreeman 0:77803b3ee157 84
JonFreeman 3:43cb067ecd00 85 BufferedSerial gps_module (D1, D0, 2048, 4, NULL); // For gps - added July 2020
JonFreeman 3:43cb067ecd00 86
JonFreeman 0:77803b3ee157 87 /*
JonFreeman 0:77803b3ee157 88 MODULE PIN USAGE
JonFreeman 3:43cb067ecd00 89 1 PA_9 D1 LocalCom Tx FUTURE i2c to enable 3rd independent pwm
JonFreeman 3:43cb067ecd00 90 2 PA_10 D0 LocalCom Rx FUTURE i2c to enable 3rd independent pwm
JonFreeman 0:77803b3ee157 91 3 NRST
JonFreeman 0:77803b3ee157 92 4 GND
JonFreeman 1:450090bdb6f4 93 5 PA12_D2 NEW June 2019 - Output engine tacho cleaned-up, brought out to testpoint 4
JonFreeman 0:77803b3ee157 94 6 PB_0 D3 AnalogIn Ext_Rev_Demand
JonFreeman 0:77803b3ee157 95 7 PB_7 D4 SDA i2c to 24LC memory
JonFreeman 0:77803b3ee157 96 8 PB_6 D5 SCL i2c to 24LC memory
JonFreeman 0:77803b3ee157 97 9 PB_12 D6 PwmOut PWM_OSC_IN Timebase for pwm, also determines max duty ratio
JonFreeman 0:77803b3ee157 98 10 N.C.
JonFreeman 0:77803b3ee157 99 11 N.C.
JonFreeman 1:450090bdb6f4 100 12 PA_8 D9 InterruptIn pulse_tacho from engine magneto, used to measure rpm
JonFreeman 3:43cb067ecd00 101 13 PA_11 D10 Speed_Control servo
JonFreeman 1:450090bdb6f4 102 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 103 15 PB_4 D12 Scope_probe
JonFreeman 0:77803b3ee157 104 16 PB_3 D13 LED Onboard LED
JonFreeman 0:77803b3ee157 105 17 3V3
JonFreeman 0:77803b3ee157 106 18 AREF
JonFreeman 1:450090bdb6f4 107 19 PA_0 A0 AnalogIn Ammeter_Ref
JonFreeman 0:77803b3ee157 108 20 PA_1 A1 AnalogIn Ammeter_In
JonFreeman 0:77803b3ee157 109 21 PA_3 A2 PWM analogue out
JonFreeman 1:450090bdb6f4 110 22 PA_4 A3 AnalogIn Driver_Pot
JonFreeman 0:77803b3ee157 111 23 PA_5 A4 n.c. SDA_IN paralleled to i2c pin, necessary because i2c has to be bit banged
JonFreeman 0:77803b3ee157 112 24 PA_6 A5 n.c. SCL_IN paralleled to i2c pin, necessary because i2c has to be bit banged
JonFreeman 1:450090bdb6f4 113 25 PA_7 A6 AnalogIn V_Sample system link voltage
JonFreeman 1:450090bdb6f4 114 26 PA_2 A7 Not used
JonFreeman 0:77803b3ee157 115 27 5V
JonFreeman 0:77803b3ee157 116 28 NRST
JonFreeman 0:77803b3ee157 117 29 GND
JonFreeman 0:77803b3ee157 118 30 VIN
JonFreeman 0:77803b3ee157 119 */
JonFreeman 0:77803b3ee157 120
JonFreeman 2:8e7b51353f32 121 // Test 6/6/2020 to get i2c working
JonFreeman 3:43cb067ecd00 122 //I2C i2c (D0, D1); // For 24LC64 eeprom correct
JonFreeman 2:8e7b51353f32 123 //I2C i2c (D1, D0); // For 24LC64 eeprom DEFINITELY WRONG
JonFreeman 2:8e7b51353f32 124 // Test 6/6/2020 to get i2c working
JonFreeman 2:8e7b51353f32 125
JonFreeman 3:43cb067ecd00 126 //InterruptIn pulse_tacho (D9); // Signal from engine magneto (clipped by I limit resistor and 3v3 zener)
JonFreeman 3:43cb067ecd00 127 // Note D9 still used but taken to rpm class object
JonFreeman 3:43cb067ecd00 128 //InterruptIn VEXT (D2); // PWM controller output folded back for cpu to monitor, useful on test to read what pwm required to do what
JonFreeman 3:43cb067ecd00 129 // Note D2 still used but taken to field class object
JonFreeman 0:77803b3ee157 130 // OUTPUTS :
JonFreeman 0:77803b3ee157 131
JonFreeman 1:450090bdb6f4 132 DigitalOut Scope_probe (D12); // Handy pin to hang scope probe onto while developing code
JonFreeman 1:450090bdb6f4 133 DigitalOut myled (LED1); // Green LED on board is PB_3 D13
JonFreeman 3:43cb067ecd00 134 //PwmOut PWM_OSC_IN (A2); // Can alter prescaler can not use A5 NOW DONE IN CLASS
JonFreeman 1:450090bdb6f4 135 //PwmOut A_OUT (A2); // Can alter prescaler can not use A5 PIN STOLEN BY PWM_OSC_IN
JonFreeman 1:450090bdb6f4 136
JonFreeman 3:43cb067ecd00 137 //PwmOut Test_RPM (PA_6);
JonFreeman 2:8e7b51353f32 138 Timer microsecs; // 64 bit counter, rolls over in half million years
JonFreeman 0:77803b3ee157 139 Ticker loop_timer; // Device to cause periodic interrupts, used to sync iterations of main programme loop - slow
JonFreeman 0:77803b3ee157 140
JonFreeman 3:43cb067ecd00 141 extern char * get_mode_text (uint32_t mode) ;
JonFreeman 3:43cb067ecd00 142
JonFreeman 3:43cb067ecd00 143
JonFreeman 3:43cb067ecd00 144 I2CEeprom eeprom (SDA_PIN, SCL_PIN, 0xa0, eeprom_page_size, 8192, 100000);
JonFreeman 3:43cb067ecd00 145 extern ee_settings_2020 user_settings ;
JonFreeman 3:43cb067ecd00 146 Engine_Manager Engine (D9, D11, D10); // Pins are magneto in, cleaned magneto out, servo, const debounce time microsecs
JonFreeman 3:43cb067ecd00 147 FieldControl Field (A2, D2); // PWM pin for MCP1630, InterruptIn for signal out of MCP1630
JonFreeman 3:43cb067ecd00 148 PCT2075 temp_sensor( SDA_PIN, SCL_PIN ); // or LM75B temp_sensor( p?, p? ); Added March 2020
JonFreeman 3:43cb067ecd00 149
JonFreeman 3:43cb067ecd00 150 //class MPL3115A2 baro ;
JonFreeman 3:43cb067ecd00 151
JonFreeman 0:77803b3ee157 152 // SYSTEM CONSTANTS
JonFreeman 0:77803b3ee157 153 /* Please Do Not Alter these */
JonFreeman 1:450090bdb6f4 154 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 155 /* End of Please Do Not Alter these */
JonFreeman 0:77803b3ee157 156 /* Global variable declarations */
JonFreeman 3:43cb067ecd00 157 uint32_t sys_timer100Hz = 0; // gets incremented by our Ticker ISR every MAIN_LOOP_REPEAT_TIME_US
JonFreeman 3:43cb067ecd00 158 uint32_t seconds = 0;
JonFreeman 3:43cb067ecd00 159 double link_volt_reading = 0.0; // Global updated by interrupt driven read of Battery Volts at rate of 100 Hz
JonFreeman 3:43cb067ecd00 160 double field_volt_reading = 0.0; // Global updated by interrupt driven read of Battery Volts at rate of 100 Hz
JonFreeman 3:43cb067ecd00 161 double amp_reading = 0.0;
JonFreeman 0:77803b3ee157 162 bool loop_flag = false; // made true in ISR_loop_timer, picked up and made false again in main programme loop
JonFreeman 1:450090bdb6f4 163 bool flag_25Hz = false; // As loop_flag but repeats 25 times per sec
JonFreeman 1:450090bdb6f4 164 bool flag_12Hz5 = false; // As loop_flag but repeats 12.5 times per sec
JonFreeman 1:450090bdb6f4 165 bool flag_1Hz = false; // As loop_flag but repeats 1 times per sec
JonFreeman 1:450090bdb6f4 166 bool query_toggle = false;
JonFreeman 0:77803b3ee157 167
JonFreeman 3:43cb067ecd00 168 bool flag_link_V_rd = false;
JonFreeman 3:43cb067ecd00 169 bool flag_field_V_rd = false;
JonFreeman 3:43cb067ecd00 170 bool flag_A_rd = false;
JonFreeman 2:8e7b51353f32 171 bool flag_Pot_rd = false;
JonFreeman 0:77803b3ee157 172
JonFreeman 3:43cb067ecd00 173 bool auto_test_flag = false;
JonFreeman 3:43cb067ecd00 174
JonFreeman 3:43cb067ecd00 175 enum {SAFE_NOTHING, POT_SERVO_DIRECT, VARIABLE_VOLTAGE, FIXED_VOLTAGE, ENG_REVS_CTRL, POT_SETS_ENGINE_RPM, CURRENT_FEEDBACK_CTRL, AUTO_TEST} ;
JonFreeman 0:77803b3ee157 176 /* End of Global variable declarations */
JonFreeman 0:77803b3ee157 177
JonFreeman 1:450090bdb6f4 178 //void ISR_fast_interrupt () { // here at 10 times main loop repeat rate (i.e. 1000Hz, 1.0ms)
JonFreeman 1:450090bdb6f4 179 void ISR_fast_interrupt () {
JonFreeman 3:43cb067ecd00 180 static uint32_t t = 0, u25 = 0;
JonFreeman 1:450090bdb6f4 181 Scope_probe = 1; // To show how much time spent in interrupt handler
JonFreeman 0:77803b3ee157 182 switch (t) {
JonFreeman 0:77803b3ee157 183 case 0:
JonFreeman 3:43cb067ecd00 184 flag_link_V_rd = true;
JonFreeman 0:77803b3ee157 185 break;
JonFreeman 3:43cb067ecd00 186 case 1:
JonFreeman 3:43cb067ecd00 187 flag_A_rd = true;
JonFreeman 3:43cb067ecd00 188 break;
JonFreeman 0:77803b3ee157 189 case 2:
JonFreeman 2:8e7b51353f32 190 flag_Pot_rd = true;
JonFreeman 2:8e7b51353f32 191 // raw_amp_offset = Ammeter_Ref.read(); // Feb 2020 Not convinced this is useful
JonFreeman 0:77803b3ee157 192 break;
JonFreeman 3:43cb067ecd00 193 case 3:
JonFreeman 3:43cb067ecd00 194 flag_field_V_rd = true;
JonFreeman 3:43cb067ecd00 195 break;
JonFreeman 3:43cb067ecd00 196 // case 4:
JonFreeman 2:8e7b51353f32 197 // driver_reading >>= 1; // Result = Result / 2
JonFreeman 2:8e7b51353f32 198 // driver_reading += Driver_Pot.read_u16();
JonFreeman 1:450090bdb6f4 199 // break;
JonFreeman 3:43cb067ecd00 200 case 5:
JonFreeman 0:77803b3ee157 201 loop_flag = true; // set flag to allow main programme loop to proceed
JonFreeman 1:450090bdb6f4 202 sys_timer100Hz++; // Just a handy measure of elapsed time for anything to use
JonFreeman 3:43cb067ecd00 203 if ((sys_timer100Hz & 0x03) == 0) { // is now 12.5Hz, not 8
JonFreeman 1:450090bdb6f4 204 flag_25Hz = true; // flag gets set 25 times per sec. Other code may clear flag and make use of this
JonFreeman 3:43cb067ecd00 205 u25++;
JonFreeman 3:43cb067ecd00 206 if (u25 == 25) {
JonFreeman 3:43cb067ecd00 207 u25 = 0;
JonFreeman 3:43cb067ecd00 208 flag_1Hz = true;
JonFreeman 3:43cb067ecd00 209 seconds++;
JonFreeman 3:43cb067ecd00 210 }
JonFreeman 3:43cb067ecd00 211 }
JonFreeman 1:450090bdb6f4 212 default:
JonFreeman 0:77803b3ee157 213 break;
JonFreeman 0:77803b3ee157 214 }
JonFreeman 0:77803b3ee157 215 t++;
JonFreeman 0:77803b3ee157 216 if (t > 9)
JonFreeman 0:77803b3ee157 217 t = 0;
JonFreeman 1:450090bdb6f4 218 Scope_probe = 0; // To show how much time spent in interrupt handler
JonFreeman 0:77803b3ee157 219 }
JonFreeman 0:77803b3ee157 220
JonFreeman 0:77803b3ee157 221 // **** End of Interrupt Service Routines ****
JonFreeman 0:77803b3ee157 222
JonFreeman 1:450090bdb6f4 223 /*double Read_Ext_Rev_Req ()
JonFreeman 1:450090bdb6f4 224 {
JonFreeman 1:450090bdb6f4 225 double rv = (double) ext_rev_req;
JonFreeman 1:450090bdb6f4 226 return rv / 4096.0;
JonFreeman 1:450090bdb6f4 227 }*/
JonFreeman 3:43cb067ecd00 228 /*
JonFreeman 1:450090bdb6f4 229 double Read_Driver_Pot ()
JonFreeman 1:450090bdb6f4 230 {
JonFreeman 1:450090bdb6f4 231 double rv = (double) driver_reading;
JonFreeman 1:450090bdb6f4 232 return rv / 4096.0;
JonFreeman 3:43cb067ecd00 233 }*/
JonFreeman 0:77803b3ee157 234
JonFreeman 3:43cb067ecd00 235 double Read_Link_Volts ()
JonFreeman 3:43cb067ecd00 236 {
JonFreeman 3:43cb067ecd00 237 return link_volt_reading * 39.9; // divisor fiddled to make voltage reading correct !
JonFreeman 0:77803b3ee157 238 }
JonFreeman 0:77803b3ee157 239
JonFreeman 3:43cb067ecd00 240 double Read_Field_Volts ()
JonFreeman 3:43cb067ecd00 241 {
JonFreeman 3:43cb067ecd00 242 return field_volt_reading * 42.85; // divisor fiddled to make voltage reading correct !
JonFreeman 0:77803b3ee157 243 }
JonFreeman 0:77803b3ee157 244
JonFreeman 3:43cb067ecd00 245 double Read_Ammeter ()
JonFreeman 3:43cb067ecd00 246 {
JonFreeman 3:43cb067ecd00 247 return amp_reading * 93.28; // Amp range corrected here
JonFreeman 1:450090bdb6f4 248 }
JonFreeman 1:450090bdb6f4 249
JonFreeman 1:450090bdb6f4 250
JonFreeman 1:450090bdb6f4 251 void query_system (struct parameters & a) {
JonFreeman 1:450090bdb6f4 252 query_toggle = !query_toggle;
JonFreeman 3:43cb067ecd00 253 }
JonFreeman 3:43cb067ecd00 254
JonFreeman 3:43cb067ecd00 255 void set_pwm (double d) { // Range 0.0 to 1.0 called from cli
JonFreeman 3:43cb067ecd00 256 Field.set_pwm (d);
JonFreeman 2:8e7b51353f32 257 }
JonFreeman 2:8e7b51353f32 258
JonFreeman 3:43cb067ecd00 259 double get_temperature () {
JonFreeman 3:43cb067ecd00 260 return (double) temp_sensor;
JonFreeman 3:43cb067ecd00 261 }
JonFreeman 3:43cb067ecd00 262
JonFreeman 3:43cb067ecd00 263 void maketable () {
JonFreeman 3:43cb067ecd00 264 Field.maketable ();
JonFreeman 2:8e7b51353f32 265 }
JonFreeman 2:8e7b51353f32 266
JonFreeman 3:43cb067ecd00 267 int32_t set_engine_RPM_lit (uint32_t RPMrequest) { // Returns actual speed
JonFreeman 3:43cb067ecd00 268 return Engine.set_RPM_literal (RPMrequest);
JonFreeman 3:43cb067ecd00 269 }
JonFreeman 2:8e7b51353f32 270
JonFreeman 3:43cb067ecd00 271 int32_t set_engine_RPM_pct (uint32_t RPMrequest) { // Returns actual speed
JonFreeman 3:43cb067ecd00 272 return Engine.set_RPM_percent (RPMrequest);
JonFreeman 3:43cb067ecd00 273 }
JonFreeman 2:8e7b51353f32 274
JonFreeman 3:43cb067ecd00 275 void auto_test_initiate (int bulb_count) {
JonFreeman 3:43cb067ecd00 276 if (Engine.running()) {
JonFreeman 3:43cb067ecd00 277 auto_test_flag = true;
JonFreeman 3:43cb067ecd00 278 pc.printf ("Requesting Auto-Test for load of %d lamps\r\n", bulb_count);
JonFreeman 3:43cb067ecd00 279 }
JonFreeman 3:43cb067ecd00 280 else {
JonFreeman 3:43cb067ecd00 281 pc.printf ("Engine not running. Can't perform auto test\r\n");
JonFreeman 3:43cb067ecd00 282 auto_test_flag = false;
JonFreeman 2:8e7b51353f32 283 }
JonFreeman 1:450090bdb6f4 284 }
JonFreeman 1:450090bdb6f4 285
JonFreeman 3:43cb067ecd00 286 void is_eng_running () {
JonFreeman 3:43cb067ecd00 287 pc.printf ("Engine%sRunning\r\n", Engine.running() ? " IS " : " NOT ");
JonFreeman 3:43cb067ecd00 288 }
JonFreeman 3:43cb067ecd00 289
JonFreeman 0:77803b3ee157 290 extern void command_line_interpreter () ; // Comms with optional pc or device using serial port through board USB socket
JonFreeman 3:43cb067ecd00 291
JonFreeman 3:43cb067ecd00 292 enum {AUTO_TEST_INACTIVE, AUTO_TEST_BEGIN, AUTO_TEST_ABORT, AUTO_TEST_IN_PROGRESS } ;
JonFreeman 0:77803b3ee157 293
JonFreeman 0:77803b3ee157 294 // Programme Entry Point
JonFreeman 0:77803b3ee157 295 int main()
JonFreeman 0:77803b3ee157 296 {
JonFreeman 2:8e7b51353f32 297 const double filt = 0.2;
JonFreeman 3:43cb067ecd00 298 const double ampfilt = 0.2;
JonFreeman 3:43cb067ecd00 299 const double vfilt = 0.2;
JonFreeman 0:77803b3ee157 300 // local variable declarations
JonFreeman 3:43cb067ecd00 301 double driver_pot = 0.0, dtmp;
JonFreeman 3:43cb067ecd00 302 int32_t temp, startup_delay, print_position = 0;
JonFreeman 3:43cb067ecd00 303 int32_t field_pct = 0, auto_test_timer = 0, auto_test_state = AUTO_TEST_INACTIVE, auto_test_step = 0;
JonFreeman 3:43cb067ecd00 304 bool up_and_running = false;
JonFreeman 3:43cb067ecd00 305 char text[64];
JonFreeman 3:43cb067ecd00 306
JonFreeman 0:77803b3ee157 307 microsecs.reset() ; // timer = 0
JonFreeman 0:77803b3ee157 308 microsecs.start () ; // 64 bit, counts micro seconds and times out in half million years
JonFreeman 1:450090bdb6f4 309
JonFreeman 3:43cb067ecd00 310 #ifdef GPS_
JonFreeman 3:43cb067ecd00 311 gps_mod gps;
JonFreeman 1:450090bdb6f4 312 #endif
JonFreeman 3:43cb067ecd00 313 //- Clear the screen, move to (0,0):
JonFreeman 3:43cb067ecd00 314 // \033[2J
JonFreeman 3:43cb067ecd00 315 pc.printf ("\033[2JAlternator Regulator 2020, Jon Freeman\r\n");
JonFreeman 3:43cb067ecd00 316 user_settings.load () ; // Fetch values from eeprom
JonFreeman 0:77803b3ee157 317 // Setup Complete ! Can now start main control forever loop.
JonFreeman 1:450090bdb6f4 318 loop_timer.attach_us (&ISR_fast_interrupt, MAIN_LOOP_REPEAT_TIME_US / 10); // Start periodic interrupt generator 1000us at Feb 2020
JonFreeman 0:77803b3ee157 319
JonFreeman 3:43cb067ecd00 320 Field.maketable () ; // Here to ensure eeprom has been setup
JonFreeman 3:43cb067ecd00 321 Field.set_for_speed (0);
JonFreeman 3:43cb067ecd00 322 Engine.Speed_Control (((double)user_settings.rd(WARMUP_SERVO_POS)) / 100.0);
JonFreeman 3:43cb067ecd00 323 startup_delay = user_settings.rd(WARM_UP_DELAY);
JonFreeman 3:43cb067ecd00 324 pc.printf ("Operating Mode is [%s]\r\n", get_mode_text (user_settings.rd(OP_MODE)));
JonFreeman 3:43cb067ecd00 325
JonFreeman 2:8e7b51353f32 326
JonFreeman 0:77803b3ee157 327 //***** START OF MAIN LOOP
JonFreeman 0:77803b3ee157 328 while (1) { // Loop forever, repeats synchroised by waiting for ticker Interrupt Service Routine to set 'loop_flag' true
JonFreeman 0:77803b3ee157 329 while (!loop_flag) { // Most of the time is spent in this loop, repeatedly re-checking for commands from pc port
JonFreeman 3:43cb067ecd00 330 #ifdef GPS_
JonFreeman 3:43cb067ecd00 331 while (gps_module.readable())
JonFreeman 3:43cb067ecd00 332 pc.putc (gps_module.getc());
JonFreeman 3:43cb067ecd00 333 #endif
JonFreeman 0:77803b3ee157 334 command_line_interpreter () ; // Proceed beyond here once loop_timer ticker ISR has set loop_flag true
JonFreeman 3:43cb067ecd00 335 // A to D converters all read at 100 Hz
JonFreeman 3:43cb067ecd00 336 if (flag_link_V_rd) {
JonFreeman 3:43cb067ecd00 337 flag_link_V_rd = false;
JonFreeman 3:43cb067ecd00 338 link_volt_reading *= (1.0 - vfilt); //
JonFreeman 3:43cb067ecd00 339 link_volt_reading += vfilt * (double) Ain_Link_Volts.read(); // Volt fiddle factor NOT corrected here
JonFreeman 2:8e7b51353f32 340 }
JonFreeman 2:8e7b51353f32 341 if (flag_Pot_rd) {
JonFreeman 2:8e7b51353f32 342 flag_Pot_rd = false;
JonFreeman 3:43cb067ecd00 343 driver_pot *= (1.0 - filt);
JonFreeman 3:43cb067ecd00 344 driver_pot += filt * ((double)Driver_Pot.read() * 1.5); // Includes bodge around zener over-clipping input
JonFreeman 3:43cb067ecd00 345 }
JonFreeman 3:43cb067ecd00 346 if (flag_A_rd) {
JonFreeman 3:43cb067ecd00 347 flag_A_rd = false;
JonFreeman 3:43cb067ecd00 348 amp_reading *= (1.0 - ampfilt);
JonFreeman 3:43cb067ecd00 349 amp_reading += ampfilt * ((double) Ammeter_In.read() - 0.5); // Amp range NOT corrected here
JonFreeman 3:43cb067ecd00 350 }
JonFreeman 3:43cb067ecd00 351 if (flag_field_V_rd) {
JonFreeman 3:43cb067ecd00 352 flag_field_V_rd = false;
JonFreeman 3:43cb067ecd00 353 field_volt_reading *= (1.0 - vfilt); //
JonFreeman 3:43cb067ecd00 354 field_volt_reading += vfilt * (double) Field_Supply_V.read(); // Volt fiddle factor NOT corrected here
JonFreeman 2:8e7b51353f32 355 }
JonFreeman 1:450090bdb6f4 356 } // Jun 2019 pass here 100 times per sec
JonFreeman 1:450090bdb6f4 357 // BEGIN 100Hz stuff
JonFreeman 3:43cb067ecd00 358 loop_flag = false; // Clear flag set by ticker interrupt handler
JonFreeman 3:43cb067ecd00 359 Engine.manager_core (); // This belongs right here, update regularly, keeps 'filtered()' fresh and keeps engine to set rpm
JonFreeman 3:43cb067ecd00 360 #ifdef GPS_
JonFreeman 3:43cb067ecd00 361 gps.update ();
JonFreeman 3:43cb067ecd00 362 #endif
JonFreeman 1:450090bdb6f4 363 // END 100Hz stuff
JonFreeman 1:450090bdb6f4 364 if (flag_25Hz) {
JonFreeman 1:450090bdb6f4 365 flag_25Hz = false;
JonFreeman 1:450090bdb6f4 366 // BEGIN 25Hz stuff
JonFreeman 0:77803b3ee157 367
JonFreeman 1:450090bdb6f4 368 // END 25Hz stuff
JonFreeman 1:450090bdb6f4 369 // BEGIN 12.5Hz stuff
JonFreeman 1:450090bdb6f4 370 flag_12Hz5 = !flag_12Hz5;
JonFreeman 1:450090bdb6f4 371 if (flag_12Hz5) { // Do any even stuff to be done 12.5 times per second
JonFreeman 3:43cb067ecd00 372 // if (up_and_running && Engine.running()) {
JonFreeman 3:43cb067ecd00 373 if (up_and_running) {
JonFreeman 3:43cb067ecd00 374 switch (user_settings.rd(OP_MODE)) {
JonFreeman 3:43cb067ecd00 375 /*
JonFreeman 3:43cb067ecd00 376 enum {SAFE_NOTHING, //
JonFreeman 3:43cb067ecd00 377 POT_SERVO_DIRECT, //
JonFreeman 3:43cb067ecd00 378 VARIABLE_VOLTAGE, // Batteryless, controllerless Low Cost Loco - alternator connects direct to DC motors
JonFreeman 3:43cb067ecd00 379 FIXED_VOLTAGE, //
JonFreeman 3:43cb067ecd00 380 ENG_REVS_CTRL, //
JonFreeman 3:43cb067ecd00 381 POT_SETS_ENGINE_RPM, //
JonFreeman 3:43cb067ecd00 382 CURRENT_FEEDBACK_CTRL, //
JonFreeman 3:43cb067ecd00 383 AUTO_TEST }; //
JonFreeman 3:43cb067ecd00 384 "0\tSafe nothing mode for cli cmd testing",
JonFreeman 3:43cb067ecd00 385 "1\tPot to Servo direct, field OFF",
JonFreeman 3:43cb067ecd00 386 "2\tVariable voltage",
JonFreeman 3:43cb067ecd00 387 "3\tFixed voltage",
JonFreeman 3:43cb067ecd00 388 "4\tEngine Revs Control",
JonFreeman 3:43cb067ecd00 389 "5\tSet Engine to Driver's Pot",
JonFreeman 3:43cb067ecd00 390 "6\tControl Engine by Current Load",
JonFreeman 3:43cb067ecd00 391 */
JonFreeman 3:43cb067ecd00 392 case SAFE_NOTHING: // Safe nothing mode for cli cmd testing
JonFreeman 3:43cb067ecd00 393 // Use this to test command line commands e.g. Speed_Control, direct field setting etc
JonFreeman 3:43cb067ecd00 394 break;
JonFreeman 3:43cb067ecd00 395
JonFreeman 3:43cb067ecd00 396 case POT_SERVO_DIRECT: // Driver_pot --> servo direct. Field OFF
JonFreeman 3:43cb067ecd00 397 Engine.Speed_Control (driver_pot);
JonFreeman 3:43cb067ecd00 398 Field.set_for_speed (0); // Safe, no output
JonFreeman 3:43cb067ecd00 399 break;
JonFreeman 3:43cb067ecd00 400
JonFreeman 3:43cb067ecd00 401 case VARIABLE_VOLTAGE: // Variable Voltage
JonFreeman 3:43cb067ecd00 402 Engine.Speed_Control (driver_pot); // Driver_pot --> servo direct. Field ON
JonFreeman 3:43cb067ecd00 403 if (driver_pot > DRIVER_NEUTRAL) // if pot not close to zero
JonFreeman 3:43cb067ecd00 404 Field.set_for_speed (Engine.RPM_latest()); // according to RPM
JonFreeman 3:43cb067ecd00 405 else
JonFreeman 3:43cb067ecd00 406 Field.set_for_speed (0); // Field OFF
JonFreeman 3:43cb067ecd00 407 break;
JonFreeman 3:43cb067ecd00 408
JonFreeman 3:43cb067ecd00 409 case FIXED_VOLTAGE: // Fixed Voltage
JonFreeman 3:43cb067ecd00 410 Field.set_for_speed (Engine.RPM_latest()); // according to RPM
JonFreeman 3:43cb067ecd00 411 break;
JonFreeman 3:43cb067ecd00 412
JonFreeman 3:43cb067ecd00 413 case ENG_REVS_CTRL: // Engine revs control - Pot to control revs over range tickover to MAX_RPM_LIMIT
JonFreeman 3:43cb067ecd00 414 Field.set_for_speed (Engine.RPM_latest());
JonFreeman 3:43cb067ecd00 415 break;
JonFreeman 3:43cb067ecd00 416
JonFreeman 3:43cb067ecd00 417 case POT_SETS_ENGINE_RPM: // Set engine to driver pot
JonFreeman 3:43cb067ecd00 418 dtmp = driver_pot * (MAX_RPM_LIMIT - TICKOVER_RPM) + TICKOVER_RPM;
JonFreeman 3:43cb067ecd00 419 temp = (int32_t) dtmp;
JonFreeman 3:43cb067ecd00 420 Engine.set_RPM_literal (temp); // this sets engine speed controller
JonFreeman 3:43cb067ecd00 421 Field.set_for_speed (Engine.RPM_latest()); // according to RPM
JonFreeman 3:43cb067ecd00 422 break;
JonFreeman 3:43cb067ecd00 423
JonFreeman 3:43cb067ecd00 424 // case CURRENT_MODE: // Set engine speed determined by current drawn
JonFreeman 3:43cb067ecd00 425 case CURRENT_FEEDBACK_CTRL: // Set engine speed determined by current drawn
JonFreeman 3:43cb067ecd00 426 temp = 0; // an integer. Engine set to tickover when no power demand
JonFreeman 3:43cb067ecd00 427 if (driver_pot > DRIVER_NEUTRAL) // if pot not close to zero
JonFreeman 3:43cb067ecd00 428 temp = 1 + (int32_t)abs(Read_Ammeter() * 8.0); // Sets max amps to 100 / 8.0
JonFreeman 3:43cb067ecd00 429 Engine.set_RPM_percent (temp); // this sets engine speed controller
JonFreeman 3:43cb067ecd00 430 Field.set_for_speed (Engine.RPM_latest()); // according to RPM
JonFreeman 3:43cb067ecd00 431 break;
JonFreeman 3:43cb067ecd00 432
JonFreeman 3:43cb067ecd00 433 case AUTO_TEST: // cli command may initiate test sequence implemented here. Wait for flag to proceed.
JonFreeman 3:43cb067ecd00 434 switch (auto_test_state) {
JonFreeman 3:43cb067ecd00 435 case AUTO_TEST_INACTIVE:
JonFreeman 3:43cb067ecd00 436 if (auto_test_flag) // cli has requested auto test sequence
JonFreeman 3:43cb067ecd00 437 auto_test_state = AUTO_TEST_BEGIN;
JonFreeman 3:43cb067ecd00 438 break;
JonFreeman 3:43cb067ecd00 439
JonFreeman 3:43cb067ecd00 440 case AUTO_TEST_BEGIN: // set engine, field etc, then initiate settling time delay
JonFreeman 3:43cb067ecd00 441 Engine.set_RPM_percent (1); // this sets engine speed controller for min useful revs
JonFreeman 3:43cb067ecd00 442 Field.set_for_speed (0);
JonFreeman 3:43cb067ecd00 443 pc.printf ("Starting auto test sequence, user field limit values :\r\n");
JonFreeman 3:43cb067ecd00 444 for (int i = 0; i < 21; i++)
JonFreeman 3:43cb067ecd00 445 pc.printf ("%d, ", user_settings.rd(i));
JonFreeman 3:43cb067ecd00 446 pc.printf ("\r\n");
JonFreeman 3:43cb067ecd00 447 auto_test_step = 0;
JonFreeman 3:43cb067ecd00 448 auto_test_timer = 0;
JonFreeman 3:43cb067ecd00 449 auto_test_state = AUTO_TEST_IN_PROGRESS;
JonFreeman 3:43cb067ecd00 450 break;
JonFreeman 3:43cb067ecd00 451
JonFreeman 3:43cb067ecd00 452 case AUTO_TEST_IN_PROGRESS: // take sets of readings, then timeout back to INACTIVE
JonFreeman 3:43cb067ecd00 453 field_pct = Field.set_for_speed (Engine.RPM_latest()); // according to RPM
JonFreeman 3:43cb067ecd00 454 switch (auto_test_timer++) { // When active, get here @ 12.5Hz
JonFreeman 3:43cb067ecd00 455 case 30: case 40: case 50: case 60: // take readings at these times
JonFreeman 3:43cb067ecd00 456 case 35: case 45: case 55: case 65:
JonFreeman 3:43cb067ecd00 457 // pc.printf ("\tTaking auto_test readings %d, Volts, Amps, RPM req, RPM got, servo position, measured duty ratio\r\n", auto_test_timer);
JonFreeman 3:43cb067ecd00 458 /*
JonFreeman 3:43cb067ecd00 459 Need to collect here,
JonFreeman 3:43cb067ecd00 460 Volts, Amps, RPM got latest, RPM got filtered, servo position, measured duty ratio, lut pcent
JonFreeman 3:43cb067ecd00 461 */
JonFreeman 3:43cb067ecd00 462 pc.printf ("\t%.2f, %.2f, %.2f, %d, %d, %.2f, %.3f, %d\r\n", Read_Link_Volts(), Read_Field_Volts(),
JonFreeman 3:43cb067ecd00 463 Read_Ammeter(), Engine.RPM_latest(), Engine.RPM_filtered(),
JonFreeman 3:43cb067ecd00 464 Engine.get_servo_position(), Field.get_duty_ratio(), field_pct);
JonFreeman 3:43cb067ecd00 465 break;
JonFreeman 3:43cb067ecd00 466 case 66: // After final set of readings
JonFreeman 3:43cb067ecd00 467 auto_test_step++;
JonFreeman 3:43cb067ecd00 468 if (auto_test_step > 10)
JonFreeman 3:43cb067ecd00 469 auto_test_state = AUTO_TEST_ABORT;
JonFreeman 3:43cb067ecd00 470 else { // set conditions for next set of readings
JonFreeman 3:43cb067ecd00 471 temp = Engine.RPM_percent_to_actual(auto_test_step * 10);
JonFreeman 3:43cb067ecd00 472 Engine.set_RPM_percent (auto_test_step * 10);
JonFreeman 3:43cb067ecd00 473 auto_test_timer = 0;
JonFreeman 3:43cb067ecd00 474 pc.printf ("Setting rig for %d percent, %d RPM\r\n", auto_test_step * 10, temp);
JonFreeman 3:43cb067ecd00 475 }
JonFreeman 3:43cb067ecd00 476 break;
JonFreeman 3:43cb067ecd00 477 default:
JonFreeman 3:43cb067ecd00 478 break;
JonFreeman 3:43cb067ecd00 479 }
JonFreeman 3:43cb067ecd00 480 break;
JonFreeman 3:43cb067ecd00 481
JonFreeman 3:43cb067ecd00 482 case AUTO_TEST_ABORT: // Here at test end or because auto_test_flag made false somewhere somehow
JonFreeman 3:43cb067ecd00 483 Engine.set_RPM_percent (0); // this sets engine speed controller
JonFreeman 3:43cb067ecd00 484 Field.set_for_speed (0);
JonFreeman 3:43cb067ecd00 485 auto_test_state = AUTO_TEST_INACTIVE;
JonFreeman 3:43cb067ecd00 486 auto_test_flag = false;
JonFreeman 3:43cb067ecd00 487 pc.printf ("Ending auto test sequence\r\n");
JonFreeman 3:43cb067ecd00 488 break;
JonFreeman 3:43cb067ecd00 489 default:
JonFreeman 3:43cb067ecd00 490 break;
JonFreeman 3:43cb067ecd00 491 } // END OF SWITCH auto_test_state
JonFreeman 3:43cb067ecd00 492 break;
JonFreeman 3:43cb067ecd00 493 default:
JonFreeman 3:43cb067ecd00 494 user_settings.wr (0, OP_MODE); // set to safe non-mode 0
JonFreeman 3:43cb067ecd00 495 break;
JonFreeman 1:450090bdb6f4 496 }
JonFreeman 1:450090bdb6f4 497 }
JonFreeman 3:43cb067ecd00 498 else { // Engine not running
JonFreeman 3:43cb067ecd00 499 Field.set_for_speed (0); // according to RPM
JonFreeman 3:43cb067ecd00 500 }
JonFreeman 1:450090bdb6f4 501 }
JonFreeman 1:450090bdb6f4 502 else { // Do odd 12.5 times per sec stuff
JonFreeman 1:450090bdb6f4 503 flag_12Hz5 = false;
JonFreeman 1:450090bdb6f4 504 myled = !myled;
JonFreeman 1:450090bdb6f4 505 } // End of if(flag_12Hz5)
JonFreeman 1:450090bdb6f4 506 // END 12.5Hz stuff
JonFreeman 3:43cb067ecd00 507 if (flag_1Hz) {
JonFreeman 1:450090bdb6f4 508 // BEGIN 1Hz stuff
JonFreeman 3:43cb067ecd00 509 flag_1Hz = false;
JonFreeman 3:43cb067ecd00 510 if (!up_and_running) {
JonFreeman 3:43cb067ecd00 511 if (startup_delay == 0) {
JonFreeman 3:43cb067ecd00 512 up_and_running = true;
JonFreeman 3:43cb067ecd00 513 pc.printf ("Warmup ended, starting proper ops\r\n");
JonFreeman 3:43cb067ecd00 514 Engine.Speed_Control (0.0);
JonFreeman 3:43cb067ecd00 515 }
JonFreeman 3:43cb067ecd00 516 else {
JonFreeman 3:43cb067ecd00 517 pc.printf ("In Startup warmup delay %d\r", startup_delay--);
JonFreeman 3:43cb067ecd00 518 }
JonFreeman 3:43cb067ecd00 519 }
JonFreeman 1:450090bdb6f4 520 if (query_toggle) {
JonFreeman 3:43cb067ecd00 521 sprintf (text, "\033[%d;0HI=%.1fA, V=%.2fV, ", 20 + print_position, Read_Ammeter() , Read_Link_Volts());
JonFreeman 3:43cb067ecd00 522 pc.printf ("%sRPM %d, rpm_set %d, pot %.3f, servo %.3f \r\n", text, Engine.RPM_latest(), Engine.get_RPM_requested (), driver_pot, Engine.get_servo_position());
JonFreeman 3:43cb067ecd00 523 print_position++;
JonFreeman 3:43cb067ecd00 524 if (print_position > 10)
JonFreeman 3:43cb067ecd00 525 print_position = 0;
JonFreeman 1:450090bdb6f4 526 }
JonFreeman 3:43cb067ecd00 527 //printf("\033[6;3HHello\n");
JonFreeman 3:43cb067ecd00 528 // pc.printf ("\033[0;1HSecs %d \r\n", seconds);
JonFreeman 3:43cb067ecd00 529 // pc.printf ("Temp = %.1f\r", get_temperature());
JonFreeman 3:43cb067ecd00 530 // gps.update();
JonFreeman 3:43cb067ecd00 531 #ifdef GPS_
JonFreeman 3:43cb067ecd00 532 if (gps.new_data()) {
JonFreeman 3:43cb067ecd00 533 myled = !myled;
JonFreeman 3:43cb067ecd00 534 pc.printf("\033[0;1H%s, %s, %s \r\n", gps.time(), gps.latitude(), gps.longitude());
JonFreeman 3:43cb067ecd00 535 pc.printf("alt ^%s^, sats %s lat mer %f, lon mer %f \r\n", gps.altitude(), gps.sat_count(), gps.lat_merged(), gps.lon_merged());
JonFreeman 3:43cb067ecd00 536 pc.printf("%s, heading %s, mph %s \r\n", gps.date(), gps.heading(), gps.mph());
JonFreeman 3:43cb067ecd00 537 pc.printf("%s\r\n \n .\r\n ", gps.message(1));
JonFreeman 3:43cb067ecd00 538 }
JonFreeman 3:43cb067ecd00 539 #endif
JonFreeman 3:43cb067ecd00 540 // while (gps_module.readable())
JonFreeman 3:43cb067ecd00 541 // pc.putc (gps_module.getc());
JonFreeman 1:450090bdb6f4 542 // END 1Hz stuff
JonFreeman 0:77803b3ee157 543 } // eo once per second stuff
JonFreeman 1:450090bdb6f4 544 } // End of 100Hz stuff
JonFreeman 0:77803b3ee157 545 } // End of main programme loop
JonFreeman 0:77803b3ee157 546 } // End of main function - end of programme
JonFreeman 3:43cb067ecd00 547