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 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