Touch screen drivers control dashboard for miniature locomotive. Features meters for speed, volts, power. Switches for lights, horns. Drives multiple STM3_ESC brushless motor controllers for complete brushless loco system as used in "The Brute" - www.jons-workshop.com
Dependencies: TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM
main.cpp@14:6bcec5ac21ca, 2019-03-04 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Mar 04 17:47:27 2019 +0000
- Revision:
- 14:6bcec5ac21ca
- Parent:
- 12:a25bdf135348
'Brute' Locomotive Touch Screen Controller - Driver's Controls; Always a 'Work In Progress', snapshot March 2019
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JonFreeman | 4:67478861c670 | 1 | /* |
JonFreeman | 12:a25bdf135348 | 2 | November 2018 - Jon Freeman |
JonFreeman | 12:a25bdf135348 | 3 | Cloned from Loco_TS_2018_06 on 23rd November 2018 |
JonFreeman | 4:67478861c670 | 4 | |
JonFreeman | 12:a25bdf135348 | 5 | Touch Screen controller communicates with 1, 2, ... n Brushless STM3 Controller boards via opto-isolated serial port. |
JonFreeman | 4:67478861c670 | 6 | |
JonFreeman | 4:67478861c670 | 7 | 9 pid D connector retained but wiring NOT compatible with 2017. |
JonFreeman | 4:67478861c670 | 8 | This time pins are : - |
JonFreeman | 4:67478861c670 | 9 | 1 Not Used on TS2018, connection from Twin BLDC Controller only - Pot wiper |
JonFreeman | 4:67478861c670 | 10 | 2 Not Used on TS2018, connection from Twin BLDC Controller only - GND |
JonFreeman | 4:67478861c670 | 11 | 3 Not Used on TS2018, connection from Twin BLDC Controller only - Weak +5 (top of pot) |
JonFreeman | 12:a25bdf135348 | 12 | 4 Not Used on TS2018, connection from Twin BLDC Controller only - Fwd / Rev switched between pins 2 and 3 above |
JonFreeman | 4:67478861c670 | 13 | 5 TS2018 high voltage output - power up signal to Twin BLDC Controllers, +10 to + 70 Volt (full supply via 3k3 0.5W safety resistor) |
JonFreeman | 4:67478861c670 | 14 | 6 Twin BLDC Rx- <- TS2018 Tx data ||GND to avoid exposing TS +5v rail to the outside world |
JonFreeman | 4:67478861c670 | 15 | 7 Twin BLDC Rx+ <- TS2018 +5v ||Tx\ to avoid exposing TS +5v rail to the outside world, INVERTED Txd idles lo |
JonFreeman | 4:67478861c670 | 16 | 8 Twin BLDC Tx- <- TS2018 GND |
JonFreeman | 4:67478861c670 | 17 | 9 Twin BLDC Tx+ <- TS2018 Rx data with 1k pullup to +5, line idles hi |
JonFreeman | 4:67478861c670 | 18 | */ |
adustm | 0:99e26e18b424 | 19 | #include "mbed.h" |
JonFreeman | 4:67478861c670 | 20 | #include "Electric_Loco.h" |
JonFreeman | 5:21a8ac83142c | 21 | #include "AsyncSerial.hpp" |
JonFreeman | 5:21a8ac83142c | 22 | #include "Servo.h" |
JonFreeman | 4:67478861c670 | 23 | #include "TS_DISCO_F746NG.h" |
JonFreeman | 4:67478861c670 | 24 | #include "LCD_DISCO_F746NG.h" |
JonFreeman | 12:a25bdf135348 | 25 | |
JonFreeman | 12:a25bdf135348 | 26 | char const_version_string[] = {"1.0.0\0"}; // Version string, readable from serial ports |
JonFreeman | 12:a25bdf135348 | 27 | |
JonFreeman | 12:a25bdf135348 | 28 | LCD_DISCO_F746NG lcd ; // LCD display |
JonFreeman | 12:a25bdf135348 | 29 | TS_DISCO_F746NG touch_screen ; // Touch Screen |
JonFreeman | 12:a25bdf135348 | 30 | screen_touch_handler slider ; // Loco driver's slider control |
JonFreeman | 4:67478861c670 | 31 | |
JonFreeman | 12:a25bdf135348 | 32 | // see movingcoilmeter.h ffi |
JonFreeman | 12:a25bdf135348 | 33 | moving_coil_meter Voltmeter ( LCD_COLOR_BLACK, LCD_COLOR_WHITE, LCD_COLOR_RED, LCD_COLOR_BLUE, LCD_COLOR_MAGENTA, |
JonFreeman | 12:a25bdf135348 | 34 | VOLTMETER_X, VOLTMETER_Y, V_A_SIZE, 22.0, 61.0, 1.25 * PI, -0.25 * PI , 20, "V", ONE_DP, false), |
JonFreeman | 12:a25bdf135348 | 35 | Powermeter ( LCD_COLOR_BLACK, LCD_COLOR_WHITE, LCD_COLOR_RED, LCD_COLOR_BLUE, LCD_COLOR_BLUE, |
JonFreeman | 12:a25bdf135348 | 36 | AMMETER_X, AMMETER_Y, V_A_SIZE, -1400.0, 1400.0, 1.25 * PI, -0.25 * PI , 14, "Watt", NO_DPS, false), |
JonFreeman | 12:a25bdf135348 | 37 | Speedo ( SPEEDO_BODY_COLOUR, SPEEDO_DIAL_COLOUR, LCD_COLOR_RED, SPEEDO_TEXT_COLOUR, LCD_COLOR_BLACK, |
JonFreeman | 12:a25bdf135348 | 38 | SPEEDO_X, SPEEDO_Y, SPEEDO_SIZE, 0.0, 12.0, 1.25 * PI, -0.25 * PI , 12, "MPH", ONE_DP, false); |
JonFreeman | 12:a25bdf135348 | 39 | // 3 instances of moving coil meter graphic |
JonFreeman | 4:67478861c670 | 40 | |
JonFreeman | 12:a25bdf135348 | 41 | error_handling_Jan_2019 Controller_Error ; // Provides array usable to store error codes. |
JonFreeman | 12:a25bdf135348 | 42 | STM3_ESC_Interface My_STM3_ESC_boards ; |
JonFreeman | 12:a25bdf135348 | 43 | |
JonFreeman | 12:a25bdf135348 | 44 | extern command_line_interpreter_core pcli, ploco; // pcli handles comms with pc, ploco handles comms with STM3_ESC boards |
JonFreeman | 4:67478861c670 | 45 | |
JonFreeman | 12:a25bdf135348 | 46 | /* |
JonFreeman | 12:a25bdf135348 | 47 | STRANGE BEHAVIOUR WARNING ! |
JonFreeman | 12:a25bdf135348 | 48 | This project requires two serial ports. |
JonFreeman | 12:a25bdf135348 | 49 | The following combination of one 'Serial' and one 'AsyncSerial' is the only combination found to work ! |
JonFreeman | 12:a25bdf135348 | 50 | MODSERIAL has not been adapted to F746NG, will not compile. |
JonFreeman | 12:a25bdf135348 | 51 | Does compile with BufferedSerial but crashes the whole thing. No startup. |
JonFreeman | 12:a25bdf135348 | 52 | */ |
JonFreeman | 4:67478861c670 | 53 | |
JonFreeman | 12:a25bdf135348 | 54 | Serial pc (USBTX, USBRX); // AsyncSerial does not work here. Comms to 'PuTTY' or similar comms programme on pc |
JonFreeman | 12:a25bdf135348 | 55 | AsyncSerial com2escs (A4, A5); // Com port to opto isolators on Twin BLDC Controller boards. Only AsyncSerial works here |
JonFreeman | 12:a25bdf135348 | 56 | |
JonFreeman | 12:a25bdf135348 | 57 | //DigitalOut reverse_pin (D7); // These pins no longer used to set mode and direction, now commands issued to com |
JonFreeman | 12:a25bdf135348 | 58 | //DigitalOut forward_pin (D9); //was D6, these two decode to fwd, rev, regen_braking and park |
JonFreeman | 12:a25bdf135348 | 59 | |
JonFreeman | 12:a25bdf135348 | 60 | DigitalOut I_sink1 (D14); // a horn |
JonFreeman | 12:a25bdf135348 | 61 | DigitalOut I_sink2 (D15); // lamp |
JonFreeman | 12:a25bdf135348 | 62 | DigitalOut I_sink3 (D3); // lamp |
JonFreeman | 12:a25bdf135348 | 63 | DigitalOut I_sink4 (D4); |
JonFreeman | 12:a25bdf135348 | 64 | DigitalOut I_sink5 (D5); |
JonFreeman | 12:a25bdf135348 | 65 | DigitalOut led_grn (LED1); // the only on board user led |
JonFreeman | 4:67478861c670 | 66 | |
JonFreeman | 5:21a8ac83142c | 67 | DigitalIn f_r_switch (D2); // was D0, Reads position of centre-off ignition switch |
JonFreeman | 4:67478861c670 | 68 | //DigitalIn spareio_d8 (D8); |
JonFreeman | 5:21a8ac83142c | 69 | //DigitalIn spareio_d9 (D9); |
JonFreeman | 4:67478861c670 | 70 | DigitalIn spareio_d10 (D10); // D8, D9, D10 wired to jumper on pcb - not used to Apr 2017 |
JonFreeman | 4:67478861c670 | 71 | |
JonFreeman | 4:67478861c670 | 72 | AnalogIn ht_volts_ain (A0); // Jan 2017 |
JonFreeman | 4:67478861c670 | 73 | AnalogIn ht_amps_ain (A1); // Jan 2017 |
JonFreeman | 5:21a8ac83142c | 74 | //AnalogIn spare_ain2 (A2); |
JonFreeman | 5:21a8ac83142c | 75 | //AnalogIn spare_ain3 (A3); |
JonFreeman | 4:67478861c670 | 76 | //AnalogIn spare_ain4 (A4); // hardware on pcb for these 3 spare analogue inputs - not used to Apr 2017 |
JonFreeman | 4:67478861c670 | 77 | //AnalogIn spare_ain5 (A5); // causes display flicker ! |
JonFreeman | 5:21a8ac83142c | 78 | |
JonFreeman | 12:a25bdf135348 | 79 | Servo servo1 (D6); // Model control servo used to adjust Honda engine speed |
JonFreeman | 4:67478861c670 | 80 | |
JonFreeman | 12:a25bdf135348 | 81 | extern bool test_qspi () ; |
JonFreeman | 4:67478861c670 | 82 | extern bool odometer_zero () ; // Returns true on success |
JonFreeman | 4:67478861c670 | 83 | extern bool odometer_update (uint32_t pulsetot, uint16_t pow, uint16_t volt) ; // Hall pulse total updated once per sec and saved in blocks of 4096 bytes on QSPI onboard memory |
JonFreeman | 4:67478861c670 | 84 | |
JonFreeman | 4:67478861c670 | 85 | extern void setup_buttons () ; |
JonFreeman | 12:a25bdf135348 | 86 | extern void rewrite_odometer () ; |
JonFreeman | 7:3b1f44cd4735 | 87 | |
JonFreeman | 4:67478861c670 | 88 | static const int |
JonFreeman | 4:67478861c670 | 89 | MAF_PTS = 140, // Moving Average Filter points. Filters reduce noise on volatage and current readings |
JonFreeman | 4:67478861c670 | 90 | FWD = 0, |
JonFreeman | 4:67478861c670 | 91 | REV = ~FWD; |
JonFreeman | 4:67478861c670 | 92 | |
JonFreeman | 12:a25bdf135348 | 93 | int32_t V_maf[MAF_PTS + 2], I_maf[MAF_PTS + 2], maf_ptr = 0; // |
JonFreeman | 12:a25bdf135348 | 94 | volatile uint32_t sys_timer_32Hz = 0; |
JonFreeman | 12:a25bdf135348 | 95 | double recent_distance = 0.0; |
adustm | 0:99e26e18b424 | 96 | |
JonFreeman | 12:a25bdf135348 | 97 | bool qtrsec_trig = false; |
JonFreeman | 12:a25bdf135348 | 98 | bool trigger_current_read = false; |
JonFreeman | 4:67478861c670 | 99 | volatile bool trigger_32ms = false; |
JonFreeman | 4:67478861c670 | 100 | |
JonFreeman | 12:a25bdf135348 | 101 | double read_voltmeter () |
JonFreeman | 4:67478861c670 | 102 | { |
JonFreeman | 7:3b1f44cd4735 | 103 | int32_t a = 0; |
JonFreeman | 4:67478861c670 | 104 | for (int b = 0; b < MAF_PTS; b++) |
JonFreeman | 12:a25bdf135348 | 105 | a += V_maf[b]; |
JonFreeman | 12:a25bdf135348 | 106 | a /= MAF_PTS; |
JonFreeman | 12:a25bdf135348 | 107 | double v = (double) a; |
JonFreeman | 12:a25bdf135348 | 108 | return (v / 932.0) + 0.0; // fiddled to suit resistor values |
JonFreeman | 12:a25bdf135348 | 109 | } |
JonFreeman | 12:a25bdf135348 | 110 | |
JonFreeman | 12:a25bdf135348 | 111 | double read_ammeter () // Returns amps taken by STM3escs - amps dumped due to over-voltage |
JonFreeman | 12:a25bdf135348 | 112 | { // Could make sense to read this at up to 32 times per second |
JonFreeman | 12:a25bdf135348 | 113 | int32_t a = 0; // MAF data almost completely renewed at this rate |
JonFreeman | 12:a25bdf135348 | 114 | for (int b = 0; b < MAF_PTS; b++) // MAF updated every 250us, MAF size = MAF_PTS (once set to 140, probably still is) |
JonFreeman | 4:67478861c670 | 115 | a += I_maf[b]; |
JonFreeman | 4:67478861c670 | 116 | a /= MAF_PTS; |
JonFreeman | 7:3b1f44cd4735 | 117 | a -= 0x4000; |
JonFreeman | 7:3b1f44cd4735 | 118 | double i = (double) (0 - a); |
JonFreeman | 7:3b1f44cd4735 | 119 | return i / 200.0; // Fiddled to get current reading close enough |
JonFreeman | 4:67478861c670 | 120 | } |
JonFreeman | 4:67478861c670 | 121 | |
JonFreeman | 12:a25bdf135348 | 122 | const int BIGMAFSIZ = 8; |
JonFreeman | 12:a25bdf135348 | 123 | |
JonFreeman | 12:a25bdf135348 | 124 | class ammeter_reading { |
JonFreeman | 12:a25bdf135348 | 125 | double bigImaf[BIGMAFSIZ]; |
JonFreeman | 12:a25bdf135348 | 126 | int bigImafptr; |
JonFreeman | 12:a25bdf135348 | 127 | double amps_longave, // internal use only |
JonFreeman | 12:a25bdf135348 | 128 | amps_latest, // update() called @ 32Hz. Value stored here is average over most recent 3125us |
JonFreeman | 14:6bcec5ac21ca | 129 | amps_filtered, // Average of the BIGMAFSIZ most recent samples stored in latest |
JonFreeman | 14:6bcec5ac21ca | 130 | amps_filtered2; // Average of the BIGMAFSIZ most recent samples stored in latest |
JonFreeman | 12:a25bdf135348 | 131 | public: |
JonFreeman | 12:a25bdf135348 | 132 | ammeter_reading () { // constructor |
JonFreeman | 12:a25bdf135348 | 133 | bigImafptr = 0; |
JonFreeman | 14:6bcec5ac21ca | 134 | amps_longave = amps_latest = amps_filtered = amps_filtered2 = 0.0; |
JonFreeman | 12:a25bdf135348 | 135 | for (int i = 0; i < BIGMAFSIZ; i++) |
JonFreeman | 12:a25bdf135348 | 136 | bigImaf[i] = 0.0; |
JonFreeman | 12:a25bdf135348 | 137 | } |
JonFreeman | 12:a25bdf135348 | 138 | void update () ; // Read ammeter core, store most recent 32ms or so worth in amps_latest, 250ms average in amps_filtered |
JonFreeman | 12:a25bdf135348 | 139 | double latest () ; |
JonFreeman | 12:a25bdf135348 | 140 | double filtered() ; |
JonFreeman | 14:6bcec5ac21ca | 141 | double filtered2() ; |
JonFreeman | 12:a25bdf135348 | 142 | } Ammeter ; |
JonFreeman | 12:a25bdf135348 | 143 | |
JonFreeman | 12:a25bdf135348 | 144 | double ammeter_reading::latest () { |
JonFreeman | 12:a25bdf135348 | 145 | return amps_latest; |
JonFreeman | 4:67478861c670 | 146 | } |
JonFreeman | 4:67478861c670 | 147 | |
JonFreeman | 14:6bcec5ac21ca | 148 | double ammeter_reading::filtered2 () { |
JonFreeman | 14:6bcec5ac21ca | 149 | // could use filter without buffer, weights result more towards more frecent samples |
JonFreeman | 14:6bcec5ac21ca | 150 | return amps_filtered2; |
JonFreeman | 14:6bcec5ac21ca | 151 | } |
JonFreeman | 14:6bcec5ac21ca | 152 | |
JonFreeman | 12:a25bdf135348 | 153 | double ammeter_reading::filtered () { |
JonFreeman | 12:a25bdf135348 | 154 | return amps_filtered; |
JonFreeman | 12:a25bdf135348 | 155 | } |
JonFreeman | 12:a25bdf135348 | 156 | |
JonFreeman | 12:a25bdf135348 | 157 | void ammeter_reading::update () { |
JonFreeman | 12:a25bdf135348 | 158 | amps_latest = read_ammeter(); |
JonFreeman | 12:a25bdf135348 | 159 | amps_longave -= bigImaf[bigImafptr]; |
JonFreeman | 12:a25bdf135348 | 160 | bigImaf[bigImafptr] = amps_latest; |
JonFreeman | 12:a25bdf135348 | 161 | amps_longave += amps_latest; |
JonFreeman | 12:a25bdf135348 | 162 | bigImafptr++; |
JonFreeman | 12:a25bdf135348 | 163 | if (bigImafptr >= BIGMAFSIZ) |
JonFreeman | 12:a25bdf135348 | 164 | bigImafptr = 0; |
JonFreeman | 12:a25bdf135348 | 165 | amps_filtered = amps_longave / BIGMAFSIZ; |
JonFreeman | 14:6bcec5ac21ca | 166 | const double sampweight = (double)(1) / (double)BIGMAFSIZ; |
JonFreeman | 14:6bcec5ac21ca | 167 | const double shrinkby = 1.0 - sampweight; |
JonFreeman | 14:6bcec5ac21ca | 168 | amps_filtered2 *= shrinkby; |
JonFreeman | 14:6bcec5ac21ca | 169 | amps_filtered2 += amps_latest * sampweight; |
JonFreeman | 12:a25bdf135348 | 170 | } |
JonFreeman | 12:a25bdf135348 | 171 | |
JonFreeman | 12:a25bdf135348 | 172 | |
JonFreeman | 4:67478861c670 | 173 | // Interrupt Service Routines |
JonFreeman | 4:67478861c670 | 174 | |
JonFreeman | 4:67478861c670 | 175 | void ISR_current_reader (void) // FIXED at 250us |
JonFreeman | 4:67478861c670 | 176 | { |
JonFreeman | 4:67478861c670 | 177 | static int ms32 = 0, ms250 = 0; |
JonFreeman | 4:67478861c670 | 178 | trigger_current_read = true; // every 250us, i.e. 4kHz NOTE only sets trigger here, readings taken in main loop |
JonFreeman | 4:67478861c670 | 179 | ms32++; |
JonFreeman | 12:a25bdf135348 | 180 | if (ms32 >= 125) { // 31.25ms, not 32ms, is 32Hz |
JonFreeman | 4:67478861c670 | 181 | ms32 = 0; |
JonFreeman | 5:21a8ac83142c | 182 | sys_timer_32Hz++; // , usable anywhere as general measure of elapsed time |
JonFreeman | 4:67478861c670 | 183 | trigger_32ms = true; |
JonFreeman | 4:67478861c670 | 184 | ms250++; |
JonFreeman | 12:a25bdf135348 | 185 | if (ms250 >= 8) { |
JonFreeman | 4:67478861c670 | 186 | ms250 = 0; |
JonFreeman | 4:67478861c670 | 187 | qtrsec_trig = true; |
JonFreeman | 4:67478861c670 | 188 | } |
JonFreeman | 4:67478861c670 | 189 | } |
JonFreeman | 4:67478861c670 | 190 | } |
JonFreeman | 4:67478861c670 | 191 | |
JonFreeman | 4:67478861c670 | 192 | // End of Interrupt Service Routines |
JonFreeman | 4:67478861c670 | 193 | |
JonFreeman | 5:21a8ac83142c | 194 | void throttle (double p) { // New Apr 2018 ; servo adjusts throttle lever on Honda GX120 |
JonFreeman | 12:a25bdf135348 | 195 | const double THR_MAX = 0.92; // Values tweaked to suit servo and linkage fitted to loco power unit |
JonFreeman | 12:a25bdf135348 | 196 | const double THR_MIN = 0.09; |
JonFreeman | 12:a25bdf135348 | 197 | const double RANGE = (THR_MAX - THR_MIN); |
JonFreeman | 5:21a8ac83142c | 198 | if (p > 1.0) |
JonFreeman | 5:21a8ac83142c | 199 | p = 1.0; |
JonFreeman | 5:21a8ac83142c | 200 | if (p < 0.0) |
JonFreeman | 5:21a8ac83142c | 201 | p = 0.0; |
JonFreeman | 5:21a8ac83142c | 202 | // p = 1.0 - p; // if direction needs swapping |
JonFreeman | 5:21a8ac83142c | 203 | p *= RANGE; |
JonFreeman | 5:21a8ac83142c | 204 | p += THR_MIN; |
JonFreeman | 5:21a8ac83142c | 205 | servo1 = p; |
adustm | 0:99e26e18b424 | 206 | } |
adustm | 0:99e26e18b424 | 207 | |
JonFreeman | 5:21a8ac83142c | 208 | |
JonFreeman | 12:a25bdf135348 | 209 | void horn (int which, int onoff) { |
JonFreeman | 12:a25bdf135348 | 210 | if (which == HI_HORN) |
JonFreeman | 12:a25bdf135348 | 211 | I_sink5 = onoff; |
JonFreeman | 12:a25bdf135348 | 212 | else |
JonFreeman | 12:a25bdf135348 | 213 | I_sink4 = onoff; |
JonFreeman | 12:a25bdf135348 | 214 | } |
JonFreeman | 12:a25bdf135348 | 215 | |
JonFreeman | 12:a25bdf135348 | 216 | |
JonFreeman | 7:3b1f44cd4735 | 217 | void lights (int onoff) { |
JonFreeman | 7:3b1f44cd4735 | 218 | I_sink2 = onoff; // lamp right |
JonFreeman | 7:3b1f44cd4735 | 219 | I_sink3 = onoff; // lamp left |
JonFreeman | 7:3b1f44cd4735 | 220 | } |
JonFreeman | 4:67478861c670 | 221 | |
JonFreeman | 12:a25bdf135348 | 222 | |
JonFreeman | 12:a25bdf135348 | 223 | void draw_normal_run_screen () { |
JonFreeman | 12:a25bdf135348 | 224 | lcd.Clear(LCD_COLOR_LIGHTGRAY); |
JonFreeman | 12:a25bdf135348 | 225 | setup_buttons(); // draws buttons |
JonFreeman | 12:a25bdf135348 | 226 | slider.DrawSlider (); |
JonFreeman | 12:a25bdf135348 | 227 | // Draw 3 analogue meter movements, speedo, voltmeter, ammeter |
JonFreeman | 12:a25bdf135348 | 228 | Speedo.redraw(); |
JonFreeman | 12:a25bdf135348 | 229 | Voltmeter.redraw(); |
JonFreeman | 12:a25bdf135348 | 230 | Powermeter.redraw(); |
JonFreeman | 12:a25bdf135348 | 231 | } |
JonFreeman | 12:a25bdf135348 | 232 | |
JonFreeman | 12:a25bdf135348 | 233 | |
JonFreeman | 12:a25bdf135348 | 234 | int main() // Programme entry point |
JonFreeman | 4:67478861c670 | 235 | { |
JonFreeman | 12:a25bdf135348 | 236 | int qtr_sec = 0, seconds = 0, minutes = 0; |
JonFreeman | 12:a25bdf135348 | 237 | double electrical_power_Watt = 0.0, volts = 0.0; |
JonFreeman | 12:a25bdf135348 | 238 | |
JonFreeman | 7:3b1f44cd4735 | 239 | pc.baud (9600); |
JonFreeman | 12:a25bdf135348 | 240 | com2escs.baud (19200); |
JonFreeman | 7:3b1f44cd4735 | 241 | |
JonFreeman | 7:3b1f44cd4735 | 242 | I_sink1 = 0; // turn outputs off |
JonFreeman | 7:3b1f44cd4735 | 243 | I_sink2 = 0; // lamp right |
JonFreeman | 7:3b1f44cd4735 | 244 | I_sink3 = 0; // lamp left |
JonFreeman | 12:a25bdf135348 | 245 | I_sink4 = 0; // low horn |
JonFreeman | 12:a25bdf135348 | 246 | I_sink5 = 0; // high horn |
JonFreeman | 7:3b1f44cd4735 | 247 | spareio_d10.mode(PullUp); |
JonFreeman | 7:3b1f44cd4735 | 248 | |
JonFreeman | 12:a25bdf135348 | 249 | Ticker tick250us; // Master 4kHz interrupt timebase |
JonFreeman | 7:3b1f44cd4735 | 250 | |
JonFreeman | 7:3b1f44cd4735 | 251 | // Setup User Interrupt Vectors |
JonFreeman | 12:a25bdf135348 | 252 | tick250us.attach_us (&ISR_current_reader, 250); // count 125 interrupts to trig 31.25ms |
JonFreeman | 4:67478861c670 | 253 | |
JonFreeman | 12:a25bdf135348 | 254 | // QSPI memory is now in constant use for odometer |
JonFreeman | 12:a25bdf135348 | 255 | if (!test_qspi()) |
JonFreeman | 12:a25bdf135348 | 256 | Controller_Error.set (FAULT_QSPI, -1); // pc.printf ("Problem with qspimemcheck\r\n"); |
JonFreeman | 4:67478861c670 | 257 | |
JonFreeman | 12:a25bdf135348 | 258 | slider.direction = f_r_switch ? REV : FWD; // Only place in the code where direction gets set. Centre-Off power switch REV-OFF-FWD. |
JonFreeman | 4:67478861c670 | 259 | |
JonFreeman | 12:a25bdf135348 | 260 | My_STM3_ESC_boards.set_I_limit (0.0); |
JonFreeman | 14:6bcec5ac21ca | 261 | My_STM3_ESC_boards.set_V_limit (0.0); // zero power to motors |
JonFreeman | 14:6bcec5ac21ca | 262 | My_STM3_ESC_boards.message ("rb\r"); // regen brake mode |
JonFreeman | 14:6bcec5ac21ca | 263 | throttle (0.0); // Set revs to idle. Start engine and warm up before powering up control |
JonFreeman | 12:a25bdf135348 | 264 | pc.printf ("\r\n\n\nJon's Loco_TS_2018 Loco Controller ver %s starting, direction %s\r\n", const_version_string, slider.direction ? "Forward":"Reverse"); |
JonFreeman | 4:67478861c670 | 265 | |
JonFreeman | 4:67478861c670 | 266 | uint8_t lcd_status = touch_screen.Init(lcd.GetXSize(), lcd.GetYSize()); |
JonFreeman | 4:67478861c670 | 267 | if (lcd_status != TS_OK) { |
JonFreeman | 12:a25bdf135348 | 268 | Controller_Error.set (FAULT_TS, -1); |
JonFreeman | 12:a25bdf135348 | 269 | } |
JonFreeman | 12:a25bdf135348 | 270 | lcd.Clear(LCD_COLOR_DARKBLUE); |
JonFreeman | 12:a25bdf135348 | 271 | lcd.SetBackColor(LCD_COLOR_GREEN); |
JonFreeman | 12:a25bdf135348 | 272 | lcd.SetTextColor(LCD_COLOR_WHITE); |
JonFreeman | 12:a25bdf135348 | 273 | lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT OK", CENTER_MODE); |
JonFreeman | 4:67478861c670 | 274 | |
JonFreeman | 7:3b1f44cd4735 | 275 | // if (odometer_zero ()) |
JonFreeman | 7:3b1f44cd4735 | 276 | // pc.printf ("TRUE from odometer_zero\r\n"); |
JonFreeman | 7:3b1f44cd4735 | 277 | // else |
JonFreeman | 7:3b1f44cd4735 | 278 | // pc.printf ("FALSE from odometer_zero\r\n"); |
JonFreeman | 5:21a8ac83142c | 279 | |
JonFreeman | 7:3b1f44cd4735 | 280 | lights (1); // Headlights ON! |
JonFreeman | 7:3b1f44cd4735 | 281 | |
JonFreeman | 12:a25bdf135348 | 282 | My_STM3_ESC_boards.search_for_escs (); // Build list of connected STM3_ESC IDs |
JonFreeman | 4:67478861c670 | 283 | |
JonFreeman | 12:a25bdf135348 | 284 | /* Controller_Error.set (3, 99); |
JonFreeman | 12:a25bdf135348 | 285 | pc.printf ("%lx red\r\n", LCD_COLOR_RED); //LCD_COLOR is 0xffrrggbb |
JonFreeman | 12:a25bdf135348 | 286 | pc.printf ("%lx grn\r\n", LCD_COLOR_GREEN); |
JonFreeman | 12:a25bdf135348 | 287 | pc.printf ("%lx blu\r\n", LCD_COLOR_BLUE); |
JonFreeman | 12:a25bdf135348 | 288 | pc.printf ("%lx blk\r\n", LCD_COLOR_BLACK); |
JonFreeman | 12:a25bdf135348 | 289 | pc.printf ("%lx white\r\n", LCD_COLOR_WHITE); |
JonFreeman | 12:a25bdf135348 | 290 | */ |
JonFreeman | 12:a25bdf135348 | 291 | draw_normal_run_screen (); |
JonFreeman | 4:67478861c670 | 292 | |
JonFreeman | 12:a25bdf135348 | 293 | pc.printf ("Controller_Error.all_good() ret'd %s\r\n", Controller_Error.all_good() ? "true" : "false"); |
JonFreeman | 4:67478861c670 | 294 | |
JonFreeman | 12:a25bdf135348 | 295 | while (1) { // main prog loop |
JonFreeman | 4:67478861c670 | 296 | |
JonFreeman | 12:a25bdf135348 | 297 | pcli.sniff (); // Do any actions from command line serial port via usb link |
JonFreeman | 4:67478861c670 | 298 | |
JonFreeman | 12:a25bdf135348 | 299 | if (trigger_current_read) { // flag set in interrupt handler every 250us |
JonFreeman | 12:a25bdf135348 | 300 | trigger_current_read = false; |
JonFreeman | 12:a25bdf135348 | 301 | I_maf[maf_ptr] = ht_amps_ain.read_u16(); // Read raw ACS709 ammeter module |
JonFreeman | 12:a25bdf135348 | 302 | V_maf[maf_ptr] = ht_volts_ain.read_u16(); // Read raw system voltage |
JonFreeman | 12:a25bdf135348 | 303 | maf_ptr++; |
JonFreeman | 12:a25bdf135348 | 304 | if (maf_ptr > MAF_PTS - 1) |
JonFreeman | 12:a25bdf135348 | 305 | maf_ptr = 0; |
JonFreeman | 12:a25bdf135348 | 306 | } // endof stuff to do every 250us |
JonFreeman | 4:67478861c670 | 307 | |
JonFreeman | 12:a25bdf135348 | 308 | if (trigger_32ms == true) { // Stuff to do every 31.25 milli secs (32Hz) |
JonFreeman | 12:a25bdf135348 | 309 | trigger_32ms = false; |
JonFreeman | 12:a25bdf135348 | 310 | ploco.sniff (); // Only call within main loop, checks message responses from STM3_ESC boards |
JonFreeman | 12:a25bdf135348 | 311 | Ammeter.update (); // This updates Ammeter 'latest' and 'filtered' variables every 31.25ms |
JonFreeman | 12:a25bdf135348 | 312 | slider.HandleFingerInput (); // Do everything concerning fingers on touch screen |
JonFreeman | 12:a25bdf135348 | 313 | } // endof doing 32Hz stuff |
JonFreeman | 4:67478861c670 | 314 | |
JonFreeman | 4:67478861c670 | 315 | if (qtrsec_trig == true) { // do every quarter second stuff here |
JonFreeman | 4:67478861c670 | 316 | qtrsec_trig = false; |
JonFreeman | 12:a25bdf135348 | 317 | volts = read_voltmeter(); // voltage and current readings updated @ 250us, these are averaged over 35ms or so |
JonFreeman | 12:a25bdf135348 | 318 | electrical_power_Watt = volts * Ammeter.filtered(); // visible throughout main |
JonFreeman | 12:a25bdf135348 | 319 | // Update meters |
JonFreeman | 12:a25bdf135348 | 320 | Powermeter.set_value(electrical_power_Watt); |
JonFreeman | 12:a25bdf135348 | 321 | Voltmeter.set_value (volts); |
JonFreeman | 12:a25bdf135348 | 322 | Speedo.set_value (My_STM3_ESC_boards.mph); |
JonFreeman | 12:a25bdf135348 | 323 | |
JonFreeman | 4:67478861c670 | 324 | led_grn = !led_grn; |
JonFreeman | 14:6bcec5ac21ca | 325 | My_STM3_ESC_boards.request_mph (); // issues "'n'mph\r", takes care of cycling through available boards in sequence |
JonFreeman | 7:3b1f44cd4735 | 326 | // switch (qtr_sec) { // Can do sequential stuff quarter second apart here |
JonFreeman | 7:3b1f44cd4735 | 327 | // } // End of switch qtr_sec |
JonFreeman | 4:67478861c670 | 328 | qtr_sec++; |
JonFreeman | 4:67478861c670 | 329 | // Can do stuff once per second here |
JonFreeman | 4:67478861c670 | 330 | if(qtr_sec > 3) { |
JonFreeman | 4:67478861c670 | 331 | qtr_sec = 0; |
JonFreeman | 4:67478861c670 | 332 | seconds++; |
JonFreeman | 4:67478861c670 | 333 | if (seconds > 59) { |
JonFreeman | 4:67478861c670 | 334 | seconds = 0; |
JonFreeman | 4:67478861c670 | 335 | minutes++; |
JonFreeman | 4:67478861c670 | 336 | // do once per minute stuff here |
JonFreeman | 14:6bcec5ac21ca | 337 | Controller_Error.report_any (false); // Reset error having reported it once |
JonFreeman | 4:67478861c670 | 338 | } // fall back into once per second |
JonFreeman | 12:a25bdf135348 | 339 | if (seconds & 1) |
JonFreeman | 12:a25bdf135348 | 340 | Speedo.LED (0, LCD_COLOR_DARKGRAY); |
JonFreeman | 12:a25bdf135348 | 341 | else |
JonFreeman | 12:a25bdf135348 | 342 | Speedo.LED (0, LCD_COLOR_RED); |
JonFreeman | 14:6bcec5ac21ca | 343 | // pc.printf ("Filter test %.3f, %.3f\r\n", Ammeter.filtered(), Ammeter.filtered2()); |
JonFreeman | 12:a25bdf135348 | 344 | My_STM3_ESC_boards.message ("kd\r"); // Kick the WatchDog timers in the Twin BLDC drive boards |
JonFreeman | 12:a25bdf135348 | 345 | recent_distance += (My_STM3_ESC_boards.mph * (111.76 * 4.0)); // Convert mph to distance mm travelled in one second |
JonFreeman | 12:a25bdf135348 | 346 | uint32_t new_metres = ((uint32_t)recent_distance) / 1000; |
JonFreeman | 12:a25bdf135348 | 347 | recent_distance -= (double)(new_metres * 1000); |
JonFreeman | 12:a25bdf135348 | 348 | if (!odometer_update (new_metres, (uint16_t)electrical_power_Watt, (uint16_t)(volts * 500.0))) { |
JonFreeman | 12:a25bdf135348 | 349 | pc.printf ("Probs with odometer_update"); |
JonFreeman | 12:a25bdf135348 | 350 | Controller_Error.set (FAULT_ODOMETER, 1); |
JonFreeman | 12:a25bdf135348 | 351 | } |
JonFreeman | 12:a25bdf135348 | 352 | rewrite_odometer () ; // Update text on speedo dial face |
JonFreeman | 4:67478861c670 | 353 | } // endof if(qtr_sec > 3 |
JonFreeman | 4:67478861c670 | 354 | } // endof if (qtrsec_trig == true) { |
JonFreeman | 4:67478861c670 | 355 | } // endof while(1) main programme loop |
JonFreeman | 12:a25bdf135348 | 356 | } // endof main () |
JonFreeman | 4:67478861c670 | 357 |