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@4:67478861c670, 2018-04-09 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Apr 09 07:51:37 2018 +0000
- Revision:
- 4:67478861c670
- Parent:
- 3:33086de19b14
- Child:
- 5:21a8ac83142c
First edit of code from 2017 for new Twin BLDC controller boards
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JonFreeman | 4:67478861c670 | 1 | /* |
JonFreeman | 4:67478861c670 | 2 | April 2018 - Jon Freeman |
JonFreeman | 4:67478861c670 | 3 | |
JonFreeman | 4:67478861c670 | 4 | Touch Screen controller communicates with 1, 2, ... n Twin BLDC Controller boards via opto-isolated serial port. |
JonFreeman | 4:67478861c670 | 5 | |
JonFreeman | 4:67478861c670 | 6 | 9 pid D connector retained but wiring NOT compatible with 2017. |
JonFreeman | 4:67478861c670 | 7 | This time pins are : - |
JonFreeman | 4:67478861c670 | 8 | 1 Not Used on TS2018, connection from Twin BLDC Controller only - Pot wiper |
JonFreeman | 4:67478861c670 | 9 | 2 Not Used on TS2018, connection from Twin BLDC Controller only - GND |
JonFreeman | 4:67478861c670 | 10 | 3 Not Used on TS2018, connection from Twin BLDC Controller only - Weak +5 (top of pot) |
JonFreeman | 4:67478861c670 | 11 | 4 Not Used on TS2018, connection from Twin BLDC Controller only - Possible Fwd / Rev switched between pins 2 and 3 above |
JonFreeman | 4:67478861c670 | 12 | 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 | 13 | 6 Twin BLDC Rx- <- TS2018 Tx data ||GND to avoid exposing TS +5v rail to the outside world |
JonFreeman | 4:67478861c670 | 14 | 7 Twin BLDC Rx+ <- TS2018 +5v ||Tx\ to avoid exposing TS +5v rail to the outside world, INVERTED Txd idles lo |
JonFreeman | 4:67478861c670 | 15 | 8 Twin BLDC Tx- <- TS2018 GND |
JonFreeman | 4:67478861c670 | 16 | 9 Twin BLDC Tx+ <- TS2018 Rx data with 1k pullup to +5, line idles hi |
JonFreeman | 4:67478861c670 | 17 | */ |
adustm | 0:99e26e18b424 | 18 | #include "mbed.h" |
JonFreeman | 4:67478861c670 | 19 | #include "Electric_Loco.h" |
JonFreeman | 4:67478861c670 | 20 | #include "FastPWM.h" |
JonFreeman | 4:67478861c670 | 21 | #include "TS_DISCO_F746NG.h" |
JonFreeman | 4:67478861c670 | 22 | #include "LCD_DISCO_F746NG.h" |
JonFreeman | 4:67478861c670 | 23 | |
JonFreeman | 4:67478861c670 | 24 | LCD_DISCO_F746NG lcd; |
JonFreeman | 4:67478861c670 | 25 | TS_DISCO_F746NG touch_screen; |
JonFreeman | 4:67478861c670 | 26 | |
JonFreeman | 4:67478861c670 | 27 | FastPWM maxv (D12, 1), |
JonFreeman | 4:67478861c670 | 28 | maxi (D11, 1); // pin, prescaler value |
JonFreeman | 4:67478861c670 | 29 | Serial pc (USBTX, USBRX); // Comms to 'PuTTY' or similar comms programme on pc |
JonFreeman | 4:67478861c670 | 30 | |
JonFreeman | 4:67478861c670 | 31 | DigitalOut reverse_pin (D7); // |
JonFreeman | 4:67478861c670 | 32 | DigitalOut forward_pin (D6); //these two decode to fwd, rev, regen_braking and park |
JonFreeman | 4:67478861c670 | 33 | |
JonFreeman | 4:67478861c670 | 34 | /*New Nov 2017 |
JonFreeman | 4:67478861c670 | 35 | D14 and D15 not taken for CAN bus - bug given back because CAN bus doesn't work! |
JonFreeman | 4:67478861c670 | 36 | */ |
JonFreeman | 4:67478861c670 | 37 | //DigitalOut GfetT2 (D14); // a horn |
JonFreeman | 4:67478861c670 | 38 | //DigitalOut GfetT1 (D15); // another horn |
JonFreeman | 4:67478861c670 | 39 | DigitalOut led_grn (LED1); // the only on board user led |
JonFreeman | 4:67478861c670 | 40 | |
JonFreeman | 4:67478861c670 | 41 | DigitalIn f_r_switch (D0); // Reads position of centre-off ignition switch |
JonFreeman | 4:67478861c670 | 42 | //DigitalIn spareio_d8 (D8); |
JonFreeman | 4:67478861c670 | 43 | //DigitalOut throttle_servo_pulse_out (D8); // now defined in throttle.cpp |
JonFreeman | 4:67478861c670 | 44 | DigitalIn spareio_d9 (D9); |
JonFreeman | 4:67478861c670 | 45 | DigitalIn spareio_d10 (D10); // D8, D9, D10 wired to jumper on pcb - not used to Apr 2017 |
JonFreeman | 4:67478861c670 | 46 | |
JonFreeman | 4:67478861c670 | 47 | AnalogIn ht_volts_ain (A0); // Jan 2017 |
JonFreeman | 4:67478861c670 | 48 | AnalogIn ht_amps_ain (A1); // Jan 2017 |
JonFreeman | 4:67478861c670 | 49 | AnalogIn spare_ain2 (A2); |
JonFreeman | 4:67478861c670 | 50 | AnalogIn spare_ain3 (A3); |
JonFreeman | 4:67478861c670 | 51 | //AnalogIn spare_ain4 (A4); // hardware on pcb for these 3 spare analogue inputs - not used to Apr 2017 |
JonFreeman | 4:67478861c670 | 52 | //AnalogIn spare_ain5 (A5); // causes display flicker ! |
JonFreeman | 4:67478861c670 | 53 | Serial com (A4, A5); // Com port to opto isolators on Twin BLDC Controller boards |
JonFreeman | 4:67478861c670 | 54 | |
JonFreeman | 4:67478861c670 | 55 | /* |
JonFreeman | 4:67478861c670 | 56 | Speed now read via opto serial ports |
JonFreeman | 4:67478861c670 | 57 | |
JonFreeman | 4:67478861c670 | 58 | InterruptIn mot4hall (D2); // One Hall sensor signal from each motor fed back to measure speed |
JonFreeman | 4:67478861c670 | 59 | InterruptIn mot3hall (D3); |
JonFreeman | 4:67478861c670 | 60 | InterruptIn mot2hall (D4); |
JonFreeman | 4:67478861c670 | 61 | InterruptIn mot1hall (D5); |
JonFreeman | 4:67478861c670 | 62 | */ |
JonFreeman | 4:67478861c670 | 63 | extern bool odometer_zero () ; // Returns true on success |
JonFreeman | 4:67478861c670 | 64 | 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 | 65 | |
JonFreeman | 4:67478861c670 | 66 | extern int get_button_press (struct point & pt) ; |
JonFreeman | 4:67478861c670 | 67 | extern void displaytext (int x, int y, const int font, uint32_t BCol, uint32_t TCol, char * txt) ; |
JonFreeman | 4:67478861c670 | 68 | extern void displaytext (int x, int y, const int font, char * txt) ; |
JonFreeman | 4:67478861c670 | 69 | extern void displaytext (int x, int y, char * txt) ; |
JonFreeman | 4:67478861c670 | 70 | extern void setup_buttons () ; |
JonFreeman | 4:67478861c670 | 71 | extern void draw_numeric_keypad (int colour) ; |
JonFreeman | 4:67478861c670 | 72 | extern void draw_button_hilight (int bu, int colour) ; |
JonFreeman | 4:67478861c670 | 73 | extern void read_presses (int * a) ; |
JonFreeman | 4:67478861c670 | 74 | extern void read_keypresses (struct ky_bd & a) ; |
JonFreeman | 4:67478861c670 | 75 | extern void SliderGraphic (struct slide & q) ; |
JonFreeman | 4:67478861c670 | 76 | extern void vm_set () ; |
JonFreeman | 4:67478861c670 | 77 | extern void update_meters (double, double, double) ; |
JonFreeman | 4:67478861c670 | 78 | extern void command_line_interpreter () ; |
JonFreeman | 4:67478861c670 | 79 | |
JonFreeman | 4:67478861c670 | 80 | extern int throttle (double, double) ; // called from main every 31ms |
JonFreeman | 4:67478861c670 | 81 | |
JonFreeman | 4:67478861c670 | 82 | static const int |
JonFreeman | 4:67478861c670 | 83 | DAMPER_DECAY = 42, // Small num -> fast 'viscous damper' on dead-mans function with finger removed from panel |
JonFreeman | 4:67478861c670 | 84 | MAF_PTS = 140, // Moving Average Filter points. Filters reduce noise on volatage and current readings |
JonFreeman | 4:67478861c670 | 85 | PWM_HZ = 16000, // chosen to be above cutoff frequency of average human ear |
JonFreeman | 4:67478861c670 | 86 | // PWM_HZ = 2000, // Used this to experiment on much bigger motor |
JonFreeman | 4:67478861c670 | 87 | // MAX_PWM_TICKS = 108000000 / PWM_HZ, // 108000000 for F746N, due to cpu clock = 216 MHz |
JonFreeman | 4:67478861c670 | 88 | MAX_PWM_TICKS = SystemCoreClock / (2 * PWM_HZ), // 108000000 for F746N, due to cpu clock = 216 MHz |
JonFreeman | 4:67478861c670 | 89 | FWD = 0, |
JonFreeman | 4:67478861c670 | 90 | REV = ~FWD; |
JonFreeman | 4:67478861c670 | 91 | |
JonFreeman | 4:67478861c670 | 92 | //from .h struct slide { int position; int oldpos; int state; int direction; bool recalc_run; bool handbrake_slipping; double handbrake_effort; double loco_speed } ; |
JonFreeman | 4:67478861c670 | 93 | struct slide slider ; |
JonFreeman | 4:67478861c670 | 94 | |
adustm | 0:99e26e18b424 | 95 | |
JonFreeman | 4:67478861c670 | 96 | int V_maf[MAF_PTS + 2], I_maf[MAF_PTS + 2], maf_ptr = 0; // ********* These should be uint16_t |
JonFreeman | 4:67478861c670 | 97 | //uint32_t Hall_pulse[8] = {0,0,0,0,0,0,0,0}; // more than max number of motors |
JonFreeman | 4:67478861c670 | 98 | uint32_t Hall_pulse[8] = {1,1,1,1,1,1,1,1}; // more than max number of motors |
JonFreeman | 4:67478861c670 | 99 | uint32_t historic_distance = 0; |
JonFreeman | 4:67478861c670 | 100 | double last_pwm = 0.0; |
JonFreeman | 4:67478861c670 | 101 | |
JonFreeman | 4:67478861c670 | 102 | bool qtrsec_trig = false; |
JonFreeman | 4:67478861c670 | 103 | bool trigger_current_read = false; |
JonFreeman | 4:67478861c670 | 104 | volatile bool trigger_32ms = false; |
JonFreeman | 4:67478861c670 | 105 | |
JonFreeman | 4:67478861c670 | 106 | |
JonFreeman | 4:67478861c670 | 107 | class speed_measurement // Interrupts at qtr sec cause read of Hall_pulse counters which are incremented by transitions of Hall inputs |
JonFreeman | 4:67478861c670 | 108 | { |
JonFreeman | 4:67478861c670 | 109 | static const int SPEED_AVE_PTS = 9; // AVE_PTS - points in moving average filters |
JonFreeman | 4:67478861c670 | 110 | int speed_maf_mem [(SPEED_AVE_PTS + 1) * 2][NUMBER_OF_MOTORS], |
JonFreeman | 4:67478861c670 | 111 | latest_counter_read[NUMBER_OF_MOTORS], |
JonFreeman | 4:67478861c670 | 112 | prev_counter_read[NUMBER_OF_MOTORS], |
JonFreeman | 4:67478861c670 | 113 | mafptr; |
JonFreeman | 4:67478861c670 | 114 | int raw_filtered () ; // sum of count for all motors |
JonFreeman | 4:67478861c670 | 115 | |
JonFreeman | 4:67478861c670 | 116 | public: |
JonFreeman | 4:67478861c670 | 117 | |
JonFreeman | 4:67478861c670 | 118 | speed_measurement () { |
JonFreeman | 4:67478861c670 | 119 | memset(speed_maf_mem, 0, sizeof(speed_maf_mem)); |
JonFreeman | 4:67478861c670 | 120 | mafptr = 0; |
JonFreeman | 4:67478861c670 | 121 | memset (latest_counter_read, 0, sizeof(latest_counter_read)); |
JonFreeman | 4:67478861c670 | 122 | memset (prev_counter_read, 0, sizeof(prev_counter_read)); |
JonFreeman | 4:67478861c670 | 123 | } // constructor |
JonFreeman | 4:67478861c670 | 124 | int raw_filtered (int) ; // count for one motor |
JonFreeman | 4:67478861c670 | 125 | int RPM () ; |
JonFreeman | 4:67478861c670 | 126 | double MPH () ; |
JonFreeman | 4:67478861c670 | 127 | void qtr_sec_update () ; |
JonFreeman | 4:67478861c670 | 128 | uint32_t metres_travelled (); |
JonFreeman | 4:67478861c670 | 129 | uint32_t pulse_total (); |
JonFreeman | 4:67478861c670 | 130 | } |
JonFreeman | 4:67478861c670 | 131 | speed ; |
JonFreeman | 4:67478861c670 | 132 | |
JonFreeman | 4:67478861c670 | 133 | int speed_measurement::raw_filtered () // sum of count for all motors |
JonFreeman | 4:67478861c670 | 134 | { |
JonFreeman | 4:67478861c670 | 135 | int result = 0, a, b; |
JonFreeman | 4:67478861c670 | 136 | for (b = 0; b < NUMBER_OF_MOTORS; b++) { |
JonFreeman | 4:67478861c670 | 137 | for (a = 0; a < SPEED_AVE_PTS; a++) { |
JonFreeman | 4:67478861c670 | 138 | result += speed_maf_mem[a][b]; |
JonFreeman | 4:67478861c670 | 139 | } |
JonFreeman | 4:67478861c670 | 140 | } |
JonFreeman | 4:67478861c670 | 141 | return result; |
JonFreeman | 4:67478861c670 | 142 | } |
JonFreeman | 4:67478861c670 | 143 | |
JonFreeman | 4:67478861c670 | 144 | int speed_measurement::raw_filtered (int motor) // count for one motor |
JonFreeman | 4:67478861c670 | 145 | { |
JonFreeman | 4:67478861c670 | 146 | int result = 0, a; |
JonFreeman | 4:67478861c670 | 147 | for (a = 0; a < SPEED_AVE_PTS; a++) { |
JonFreeman | 4:67478861c670 | 148 | result += speed_maf_mem[a][motor]; |
JonFreeman | 4:67478861c670 | 149 | } |
JonFreeman | 4:67478861c670 | 150 | return result; |
JonFreeman | 4:67478861c670 | 151 | } |
JonFreeman | 4:67478861c670 | 152 | |
JonFreeman | 4:67478861c670 | 153 | double speed_measurement::MPH () |
JonFreeman | 4:67478861c670 | 154 | { |
JonFreeman | 4:67478861c670 | 155 | return rpm2mph * (double)RPM(); |
JonFreeman | 4:67478861c670 | 156 | } |
JonFreeman | 4:67478861c670 | 157 | |
JonFreeman | 4:67478861c670 | 158 | int speed_measurement::RPM () |
JonFreeman | 4:67478861c670 | 159 | { |
JonFreeman | 4:67478861c670 | 160 | int rpm = raw_filtered (); |
JonFreeman | 4:67478861c670 | 161 | rpm *= 60 * 4; // 60 sec per min, 4 quarters per sec, result pulses per min |
JonFreeman | 4:67478861c670 | 162 | rpm /= (SPEED_AVE_PTS * NUMBER_OF_MOTORS * 8); // 8 transitions counted per rev |
JonFreeman | 4:67478861c670 | 163 | return rpm; |
JonFreeman | 4:67478861c670 | 164 | } |
JonFreeman | 4:67478861c670 | 165 | |
JonFreeman | 4:67478861c670 | 166 | void speed_measurement::qtr_sec_update () // this to be called every quarter sec to read counters and update maf |
JonFreeman | 4:67478861c670 | 167 | { |
JonFreeman | 4:67478861c670 | 168 | mafptr++; |
JonFreeman | 4:67478861c670 | 169 | if (mafptr >= SPEED_AVE_PTS) |
JonFreeman | 4:67478861c670 | 170 | mafptr = 0; |
JonFreeman | 4:67478861c670 | 171 | for (int a = 0; a < NUMBER_OF_MOTORS; a++) { |
JonFreeman | 4:67478861c670 | 172 | prev_counter_read[a] = latest_counter_read[a]; |
JonFreeman | 4:67478861c670 | 173 | latest_counter_read[a] = Hall_pulse[a]; |
JonFreeman | 4:67478861c670 | 174 | speed_maf_mem[mafptr][a] = latest_counter_read[a] - prev_counter_read[a]; |
JonFreeman | 4:67478861c670 | 175 | } |
JonFreeman | 4:67478861c670 | 176 | } |
JonFreeman | 4:67478861c670 | 177 | |
JonFreeman | 4:67478861c670 | 178 | uint32_t speed_measurement::metres_travelled () |
JonFreeman | 4:67478861c670 | 179 | { |
JonFreeman | 4:67478861c670 | 180 | return pulse_total() / (int)PULSES_PER_METRE; |
JonFreeman | 4:67478861c670 | 181 | } |
adustm | 0:99e26e18b424 | 182 | |
JonFreeman | 4:67478861c670 | 183 | uint32_t speed_measurement::pulse_total () |
JonFreeman | 4:67478861c670 | 184 | { |
JonFreeman | 4:67478861c670 | 185 | return historic_distance + Hall_pulse[0] + Hall_pulse[1] + Hall_pulse[2] + Hall_pulse[3]; |
JonFreeman | 4:67478861c670 | 186 | } |
JonFreeman | 4:67478861c670 | 187 | |
JonFreeman | 4:67478861c670 | 188 | uint32_t get_pulse_total () { // called by SD card code |
JonFreeman | 4:67478861c670 | 189 | return speed.pulse_total(); |
JonFreeman | 4:67478861c670 | 190 | } |
JonFreeman | 4:67478861c670 | 191 | |
JonFreeman | 4:67478861c670 | 192 | void set_V_limit (double p) // Sets max motor voltage |
JonFreeman | 4:67478861c670 | 193 | { |
JonFreeman | 4:67478861c670 | 194 | if (p < 0.0) |
JonFreeman | 4:67478861c670 | 195 | p = 0.0; |
JonFreeman | 4:67478861c670 | 196 | if (p > 1.0) |
JonFreeman | 4:67478861c670 | 197 | p = 1.0; |
JonFreeman | 4:67478861c670 | 198 | last_pwm = p; |
JonFreeman | 4:67478861c670 | 199 | p *= 0.95; // need limit, ffi see MCP1630 data |
JonFreeman | 4:67478861c670 | 200 | p = 1.0 - p; // because pwm is wrong way up |
JonFreeman | 4:67478861c670 | 201 | maxv.pulsewidth_ticks ((int)(p * MAX_PWM_TICKS)); // PWM output on pin D12 inverted motor pwm |
JonFreeman | 4:67478861c670 | 202 | } |
JonFreeman | 4:67478861c670 | 203 | |
JonFreeman | 4:67478861c670 | 204 | void set_I_limit (double p) // Sets max motor current |
JonFreeman | 4:67478861c670 | 205 | { |
JonFreeman | 4:67478861c670 | 206 | int a; |
JonFreeman | 4:67478861c670 | 207 | if (p < 0.0) |
JonFreeman | 4:67478861c670 | 208 | p = 0.0; |
JonFreeman | 4:67478861c670 | 209 | if (p > 1.0) |
JonFreeman | 4:67478861c670 | 210 | p = 1.0; |
JonFreeman | 4:67478861c670 | 211 | a = (int)(p * MAX_PWM_TICKS); |
JonFreeman | 4:67478861c670 | 212 | if (a > MAX_PWM_TICKS) |
JonFreeman | 4:67478861c670 | 213 | a = MAX_PWM_TICKS; |
JonFreeman | 4:67478861c670 | 214 | if (a < 0) |
JonFreeman | 4:67478861c670 | 215 | a = 0; |
JonFreeman | 4:67478861c670 | 216 | maxi.pulsewidth_ticks (a); // PWM output on pin D12 inverted motor pwm |
JonFreeman | 4:67478861c670 | 217 | } |
JonFreeman | 4:67478861c670 | 218 | |
JonFreeman | 4:67478861c670 | 219 | double read_ammeter () |
JonFreeman | 4:67478861c670 | 220 | { |
JonFreeman | 4:67478861c670 | 221 | int a = 0; |
JonFreeman | 4:67478861c670 | 222 | for (int b = 0; b < MAF_PTS; b++) |
JonFreeman | 4:67478861c670 | 223 | a += I_maf[b]; |
JonFreeman | 4:67478861c670 | 224 | a /= MAF_PTS; |
JonFreeman | 4:67478861c670 | 225 | double i = (double) a; |
JonFreeman | 4:67478861c670 | 226 | return (i * 95.0 / 32768.0) - 95.0 + 0.46; // fiddled to suit current module |
JonFreeman | 4:67478861c670 | 227 | } |
JonFreeman | 4:67478861c670 | 228 | |
JonFreeman | 4:67478861c670 | 229 | double read_voltmeter () |
JonFreeman | 4:67478861c670 | 230 | { |
JonFreeman | 4:67478861c670 | 231 | int a = 0; |
JonFreeman | 4:67478861c670 | 232 | for (int b = 0; b < MAF_PTS; b++) |
JonFreeman | 4:67478861c670 | 233 | a += V_maf[b]; |
JonFreeman | 4:67478861c670 | 234 | a /= MAF_PTS; |
JonFreeman | 4:67478861c670 | 235 | double i = (double) a; |
JonFreeman | 4:67478861c670 | 236 | return (i / 617.75) + 0.3; // fiddled to suit current module |
JonFreeman | 4:67478861c670 | 237 | } |
JonFreeman | 4:67478861c670 | 238 | |
JonFreeman | 4:67478861c670 | 239 | // Interrupt Service Routines |
JonFreeman | 4:67478861c670 | 240 | |
JonFreeman | 4:67478861c670 | 241 | void ISR_mot1_hall_handler () // read motor position pulse signals from up to six motors |
JonFreeman | 4:67478861c670 | 242 | { |
JonFreeman | 4:67478861c670 | 243 | Hall_pulse[0]++; |
JonFreeman | 4:67478861c670 | 244 | } |
JonFreeman | 4:67478861c670 | 245 | void ISR_mot2_hall_handler () |
JonFreeman | 4:67478861c670 | 246 | { |
JonFreeman | 4:67478861c670 | 247 | Hall_pulse[1]++; |
JonFreeman | 4:67478861c670 | 248 | } |
JonFreeman | 4:67478861c670 | 249 | void ISR_mot3_hall_handler () |
JonFreeman | 4:67478861c670 | 250 | { |
JonFreeman | 4:67478861c670 | 251 | Hall_pulse[2]++; |
JonFreeman | 4:67478861c670 | 252 | } |
JonFreeman | 4:67478861c670 | 253 | void ISR_mot4_hall_handler () |
JonFreeman | 4:67478861c670 | 254 | { |
JonFreeman | 4:67478861c670 | 255 | Hall_pulse[3]++; |
JonFreeman | 4:67478861c670 | 256 | } |
JonFreeman | 4:67478861c670 | 257 | void ISR_mot5_hall_handler () // If only 4 motors this never gets used, there is no fifth motor |
JonFreeman | 4:67478861c670 | 258 | { |
JonFreeman | 4:67478861c670 | 259 | Hall_pulse[4]++; |
JonFreeman | 4:67478861c670 | 260 | } |
JonFreeman | 4:67478861c670 | 261 | void ISR_mot6_hall_handler () // As one above |
JonFreeman | 4:67478861c670 | 262 | { |
JonFreeman | 4:67478861c670 | 263 | Hall_pulse[5]++; |
JonFreeman | 4:67478861c670 | 264 | } |
JonFreeman | 4:67478861c670 | 265 | |
adustm | 0:99e26e18b424 | 266 | |
JonFreeman | 4:67478861c670 | 267 | void ISR_current_reader (void) // FIXED at 250us |
JonFreeman | 4:67478861c670 | 268 | { |
JonFreeman | 4:67478861c670 | 269 | static int ms32 = 0, ms250 = 0; |
JonFreeman | 4:67478861c670 | 270 | trigger_current_read = true; // every 250us, i.e. 4kHz NOTE only sets trigger here, readings taken in main loop |
JonFreeman | 4:67478861c670 | 271 | ms32++; |
JonFreeman | 4:67478861c670 | 272 | if (ms32 > 124) { |
JonFreeman | 4:67478861c670 | 273 | ms32 = 0; |
JonFreeman | 4:67478861c670 | 274 | |
JonFreeman | 4:67478861c670 | 275 | historic_distance++; |
JonFreeman | 4:67478861c670 | 276 | |
JonFreeman | 4:67478861c670 | 277 | trigger_32ms = true; |
JonFreeman | 4:67478861c670 | 278 | ms250++; |
JonFreeman | 4:67478861c670 | 279 | if (ms250 > 7) { |
JonFreeman | 4:67478861c670 | 280 | ms250 = 0; |
JonFreeman | 4:67478861c670 | 281 | qtrsec_trig = true; |
JonFreeman | 4:67478861c670 | 282 | } |
JonFreeman | 4:67478861c670 | 283 | } |
JonFreeman | 4:67478861c670 | 284 | } |
JonFreeman | 4:67478861c670 | 285 | |
JonFreeman | 4:67478861c670 | 286 | // End of Interrupt Service Routines |
JonFreeman | 4:67478861c670 | 287 | |
JonFreeman | 4:67478861c670 | 288 | |
JonFreeman | 4:67478861c670 | 289 | bool inlist (struct ky_bd & a, int key) |
JonFreeman | 4:67478861c670 | 290 | { |
JonFreeman | 4:67478861c670 | 291 | int i = 0; |
JonFreeman | 4:67478861c670 | 292 | while (i < a.count) { |
JonFreeman | 4:67478861c670 | 293 | if (key == a.ky[i].keynum) |
JonFreeman | 4:67478861c670 | 294 | return true; |
JonFreeman | 4:67478861c670 | 295 | i++; |
JonFreeman | 4:67478861c670 | 296 | } |
JonFreeman | 4:67478861c670 | 297 | return false; |
JonFreeman | 4:67478861c670 | 298 | } |
JonFreeman | 4:67478861c670 | 299 | |
JonFreeman | 4:67478861c670 | 300 | |
JonFreeman | 4:67478861c670 | 301 | void stuff_to_do_every_250us () // Take readings of system voltage and current |
JonFreeman | 4:67478861c670 | 302 | { |
JonFreeman | 4:67478861c670 | 303 | if (!trigger_current_read) |
JonFreeman | 4:67478861c670 | 304 | return; |
JonFreeman | 4:67478861c670 | 305 | trigger_current_read = false; |
JonFreeman | 4:67478861c670 | 306 | I_maf[maf_ptr] = ht_amps_ain.read_u16(); |
JonFreeman | 4:67478861c670 | 307 | V_maf[maf_ptr] = ht_volts_ain.read_u16(); |
JonFreeman | 4:67478861c670 | 308 | maf_ptr++; |
JonFreeman | 4:67478861c670 | 309 | if (maf_ptr > MAF_PTS - 1) |
JonFreeman | 4:67478861c670 | 310 | maf_ptr = 0; |
JonFreeman | 4:67478861c670 | 311 | } |
JonFreeman | 4:67478861c670 | 312 | /* Feb 2017, re-thought use of FR and SG signals. Rename these FWD and REV. Truth table for actions required now : - |
JonFreeman | 4:67478861c670 | 313 | FWD(A5) REV(A4) PWM Action |
JonFreeman | 4:67478861c670 | 314 | 0 0 0 'Handbrake' - energises motor to not move |
JonFreeman | 4:67478861c670 | 315 | 0 0 1 'Handbrake' - energises motor to not move |
JonFreeman | 4:67478861c670 | 316 | 0 1 0 Reverse0 |
JonFreeman | 4:67478861c670 | 317 | 0 1 1 Reverse1 |
JonFreeman | 4:67478861c670 | 318 | |
JonFreeman | 4:67478861c670 | 319 | 1 0 0 Forward0 |
JonFreeman | 4:67478861c670 | 320 | 1 0 1 Forward1 |
JonFreeman | 4:67478861c670 | 321 | 1 1 0 Regen Braking |
JonFreeman | 4:67478861c670 | 322 | 1 1 1 Regen Braking |
JonFreeman | 4:67478861c670 | 323 | */ |
JonFreeman | 4:67478861c670 | 324 | void set_run_mode (int mode) |
JonFreeman | 4:67478861c670 | 325 | { // NOTE Nov 2017 - Handbrake not implemented |
JonFreeman | 4:67478861c670 | 326 | if (mode == HANDBRAKE_SLIPPING) slider.handbrake_slipping = true; |
JonFreeman | 4:67478861c670 | 327 | else slider.handbrake_slipping = false; |
JonFreeman | 4:67478861c670 | 328 | switch (mode) { |
JonFreeman | 4:67478861c670 | 329 | // STATES, INACTIVE, RUN, NEUTRAL_DRIFT, REGEN_BRAKE, PARK}; |
JonFreeman | 4:67478861c670 | 330 | // case HANDBRAKE_SLIPPING: |
JonFreeman | 4:67478861c670 | 331 | // break; |
JonFreeman | 4:67478861c670 | 332 | case PARK: // PARKED new rom code IS now finished. |
JonFreeman | 4:67478861c670 | 333 | forward_pin = 0; |
JonFreeman | 4:67478861c670 | 334 | reverse_pin = 0; |
JonFreeman | 4:67478861c670 | 335 | slider.state = mode; |
JonFreeman | 4:67478861c670 | 336 | set_V_limit (0.075); // was 0.1 |
JonFreeman | 4:67478861c670 | 337 | set_I_limit (slider.handbrake_effort); |
JonFreeman | 4:67478861c670 | 338 | break; |
JonFreeman | 4:67478861c670 | 339 | case REGEN_BRAKE: // BRAKING, pwm affects degree |
JonFreeman | 4:67478861c670 | 340 | forward_pin = 1; |
JonFreeman | 4:67478861c670 | 341 | reverse_pin = 1; |
JonFreeman | 4:67478861c670 | 342 | slider.state = mode; |
JonFreeman | 4:67478861c670 | 343 | break; |
JonFreeman | 4:67478861c670 | 344 | case NEUTRAL_DRIFT: |
JonFreeman | 4:67478861c670 | 345 | slider.state = mode; |
JonFreeman | 4:67478861c670 | 346 | set_I_limit (0.0); // added after first test runs, looking for cause of mechanical startup snatch |
JonFreeman | 4:67478861c670 | 347 | set_V_limit (0.0); // added after first test runs, looking for cause of mechanical startup snatch |
JonFreeman | 4:67478861c670 | 348 | break; |
JonFreeman | 4:67478861c670 | 349 | case RUN: |
JonFreeman | 4:67478861c670 | 350 | if (slider.direction) { |
JonFreeman | 4:67478861c670 | 351 | forward_pin = 0; |
JonFreeman | 4:67478861c670 | 352 | reverse_pin = 1; |
JonFreeman | 4:67478861c670 | 353 | } else { |
JonFreeman | 4:67478861c670 | 354 | forward_pin = 1; |
JonFreeman | 4:67478861c670 | 355 | reverse_pin = 0; |
JonFreeman | 4:67478861c670 | 356 | } |
JonFreeman | 4:67478861c670 | 357 | slider.state = mode; |
JonFreeman | 4:67478861c670 | 358 | break; |
JonFreeman | 4:67478861c670 | 359 | default: |
JonFreeman | 4:67478861c670 | 360 | break; |
JonFreeman | 4:67478861c670 | 361 | } |
JonFreeman | 4:67478861c670 | 362 | } |
JonFreeman | 4:67478861c670 | 363 | |
JonFreeman | 4:67478861c670 | 364 | |
JonFreeman | 4:67478861c670 | 365 | #ifdef SDCARD |
adustm | 0:99e26e18b424 | 366 | |
adustm | 0:99e26e18b424 | 367 | #define BLOCK_START_ADDR 0 /* Block start address */ |
adustm | 0:99e26e18b424 | 368 | #define NUM_OF_BLOCKS 5 /* Total number of blocks */ |
adustm | 0:99e26e18b424 | 369 | #define BUFFER_WORDS_SIZE ((BLOCKSIZE * NUM_OF_BLOCKS) >> 2) /* Total data size in bytes */ |
adustm | 0:99e26e18b424 | 370 | |
adustm | 0:99e26e18b424 | 371 | uint32_t aTxBuffer[BUFFER_WORDS_SIZE]; |
adustm | 0:99e26e18b424 | 372 | uint32_t aRxBuffer[BUFFER_WORDS_SIZE]; |
adustm | 0:99e26e18b424 | 373 | /* Private function prototypes -----------------------------------------------*/ |
adustm | 0:99e26e18b424 | 374 | void SD_main_test(void); |
adustm | 0:99e26e18b424 | 375 | void SD_Detection(void); |
adustm | 0:99e26e18b424 | 376 | |
adustm | 0:99e26e18b424 | 377 | static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset); |
adustm | 0:99e26e18b424 | 378 | static uint8_t Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint16_t BufferLength); |
adustm | 0:99e26e18b424 | 379 | /** |
adustm | 0:99e26e18b424 | 380 | * @brief Fills buffer with user predefined data. |
adustm | 0:99e26e18b424 | 381 | * @param pBuffer: pointer on the buffer to fill |
adustm | 0:99e26e18b424 | 382 | * @param uwBufferLenght: size of the buffer to fill |
adustm | 0:99e26e18b424 | 383 | * @param uwOffset: first value to fill on the buffer |
adustm | 0:99e26e18b424 | 384 | * @retval None |
adustm | 0:99e26e18b424 | 385 | */ |
adustm | 0:99e26e18b424 | 386 | static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLength, uint32_t uwOffset) |
adustm | 0:99e26e18b424 | 387 | { |
adustm | 0:99e26e18b424 | 388 | uint32_t tmpIndex = 0; |
adustm | 0:99e26e18b424 | 389 | |
adustm | 0:99e26e18b424 | 390 | /* Put in global buffer different values */ |
adustm | 0:99e26e18b424 | 391 | for (tmpIndex = 0; tmpIndex < uwBufferLength; tmpIndex++ ) |
adustm | 0:99e26e18b424 | 392 | { |
adustm | 0:99e26e18b424 | 393 | pBuffer[tmpIndex] = tmpIndex + uwOffset; |
adustm | 0:99e26e18b424 | 394 | } |
adustm | 0:99e26e18b424 | 395 | } |
adustm | 0:99e26e18b424 | 396 | |
adustm | 0:99e26e18b424 | 397 | /** |
adustm | 0:99e26e18b424 | 398 | * @brief Compares two buffers. |
adustm | 0:99e26e18b424 | 399 | * @param pBuffer1, pBuffer2: buffers to be compared. |
adustm | 0:99e26e18b424 | 400 | * @param BufferLength: buffer's length |
adustm | 0:99e26e18b424 | 401 | * @retval 1: pBuffer identical to pBuffer1 |
adustm | 0:99e26e18b424 | 402 | * 0: pBuffer differs from pBuffer1 |
adustm | 0:99e26e18b424 | 403 | */ |
adustm | 0:99e26e18b424 | 404 | static uint8_t Buffercmp(uint32_t* pBuffer1, uint32_t* pBuffer2, uint16_t BufferLength) |
adustm | 0:99e26e18b424 | 405 | { |
adustm | 0:99e26e18b424 | 406 | while (BufferLength--) |
adustm | 0:99e26e18b424 | 407 | { |
adustm | 0:99e26e18b424 | 408 | if (*pBuffer1 != *pBuffer2) |
adustm | 0:99e26e18b424 | 409 | { |
adustm | 0:99e26e18b424 | 410 | return 1; |
adustm | 0:99e26e18b424 | 411 | } |
adustm | 0:99e26e18b424 | 412 | |
adustm | 0:99e26e18b424 | 413 | pBuffer1++; |
adustm | 0:99e26e18b424 | 414 | pBuffer2++; |
adustm | 0:99e26e18b424 | 415 | } |
adustm | 0:99e26e18b424 | 416 | |
adustm | 0:99e26e18b424 | 417 | return 0; |
adustm | 0:99e26e18b424 | 418 | } |
adustm | 0:99e26e18b424 | 419 | |
JonFreeman | 4:67478861c670 | 420 | #endif |
JonFreeman | 4:67478861c670 | 421 | |
JonFreeman | 4:67478861c670 | 422 | int main() |
JonFreeman | 4:67478861c670 | 423 | { |
JonFreeman | 4:67478861c670 | 424 | #ifdef QSPI |
JonFreeman | 4:67478861c670 | 425 | |
JonFreeman | 4:67478861c670 | 426 | extern int qspifindfree (uint8_t* dest, uint32_t addr) ; |
JonFreeman | 4:67478861c670 | 427 | extern int ask_QSPI_OK () ; |
JonFreeman | 4:67478861c670 | 428 | extern bool qspimemcheck () ; |
JonFreeman | 4:67478861c670 | 429 | extern int qspiinit () ; |
JonFreeman | 4:67478861c670 | 430 | int qspi_ok = ask_QSPI_OK (); |
JonFreeman | 4:67478861c670 | 431 | //extern int qspieraseblock (uint32_t addr) ; |
JonFreeman | 4:67478861c670 | 432 | //extern int qspiwr (uint8_t* src, uint32_t addr) ; |
JonFreeman | 4:67478861c670 | 433 | //extern int qspiwr (uint8_t* src, uint32_t addr, uint32_t len) ; |
JonFreeman | 4:67478861c670 | 434 | //extern int qspird (uint8_t* dest, uint32_t addr, uint32_t len) ; |
JonFreeman | 4:67478861c670 | 435 | |
JonFreeman | 4:67478861c670 | 436 | //#define BUFFER_SIZE ((uint32_t)32) |
JonFreeman | 4:67478861c670 | 437 | //#define QSPI_BUFFER_SIZE ((uint32_t)4270) // Big enough for 4096 byte block |
JonFreeman | 4:67478861c670 | 438 | //#define WRITE_READ_ADDR ((uint32_t)0x0050) |
JonFreeman | 4:67478861c670 | 439 | //#define WRITE_READ_ADDR ((uint32_t)0x0010) |
JonFreeman | 4:67478861c670 | 440 | //#define WRITE_READ_ADDR2 ((uint32_t)0x0020) |
JonFreeman | 4:67478861c670 | 441 | //#define WRITE_READ_ADDR3 ((uint32_t)0x4030) |
JonFreeman | 4:67478861c670 | 442 | //#define QSPI_BASE_ADDR ((uint32_t)0x90000000) |
JonFreeman | 4:67478861c670 | 443 | |
JonFreeman | 4:67478861c670 | 444 | // 123456789012345 |
JonFreeman | 4:67478861c670 | 445 | // uint8_t WriteBuffer[QSPI_BUFFER_SIZE] = "Hello World !!!\0"; |
JonFreeman | 4:67478861c670 | 446 | // uint8_t ReadBuffer[QSPI_BUFFER_SIZE]; |
JonFreeman | 4:67478861c670 | 447 | // const uint8_t MemInitString[] = "Electric Locomotive Controller - Jon Freeman B. Eng. Hons - November 2017\0"; |
JonFreeman | 4:67478861c670 | 448 | // const uint8_t Ifound_String[] = "I found the man sir, god I wish I hadn't!\0"; |
JonFreeman | 4:67478861c670 | 449 | |
JonFreeman | 4:67478861c670 | 450 | // pc.printf ("[%s]\r\n", MemInitString); |
JonFreeman | 4:67478861c670 | 451 | // pc.printf ("[%s]\r\n", Ifound_String); |
JonFreeman | 4:67478861c670 | 452 | // pc.printf("\n\nQSPI demo started\r\n"); |
JonFreeman | 4:67478861c670 | 453 | |
JonFreeman | 4:67478861c670 | 454 | // Check initialization |
JonFreeman | 4:67478861c670 | 455 | if (qspiinit() != qspi_ok) |
JonFreeman | 4:67478861c670 | 456 | error("Initialization FAILED\r\n"); |
JonFreeman | 4:67478861c670 | 457 | else |
JonFreeman | 4:67478861c670 | 458 | pc.printf("Initialization PASSED\r\n"); |
JonFreeman | 4:67478861c670 | 459 | |
JonFreeman | 4:67478861c670 | 460 | // Check memory informations |
JonFreeman | 4:67478861c670 | 461 | if (!qspimemcheck ()) |
JonFreeman | 4:67478861c670 | 462 | pc.printf ("Problem with qspimemcheck\r\n"); |
JonFreeman | 4:67478861c670 | 463 | /* // Erase memory |
JonFreeman | 4:67478861c670 | 464 | qspieraseblock (WRITE_READ_ADDR); |
JonFreeman | 4:67478861c670 | 465 | qspieraseblock (WRITE_READ_ADDR2); |
JonFreeman | 4:67478861c670 | 466 | qspieraseblock (WRITE_READ_ADDR3); |
JonFreeman | 4:67478861c670 | 467 | qspieraseblock (0x02000); |
JonFreeman | 4:67478861c670 | 468 | // Write memory |
JonFreeman | 4:67478861c670 | 469 | qspiwr(WriteBuffer, WRITE_READ_ADDR); |
JonFreeman | 4:67478861c670 | 470 | qspird(ReadBuffer, WRITE_READ_ADDR, 20); |
JonFreeman | 4:67478861c670 | 471 | qspiwr((uint8_t*)"Oh what a joy it is.", 0x02000); |
JonFreeman | 4:67478861c670 | 472 | qspird(ReadBuffer, 0x02000, 20); |
JonFreeman | 4:67478861c670 | 473 | qspieraseblock (0x02000); |
JonFreeman | 4:67478861c670 | 474 | */ // Read memory |
JonFreeman | 4:67478861c670 | 475 | // if (qspi.Read(ReadBuffer, WRITE_READ_ADDR, 11) != QSPI_OK) |
JonFreeman | 4:67478861c670 | 476 | /* qspird(ReadBuffer, WRITE_READ_ADDR, 256); |
JonFreeman | 4:67478861c670 | 477 | qspird(ReadBuffer, WRITE_READ_ADDR + 1, 256); |
JonFreeman | 4:67478861c670 | 478 | qspird(ReadBuffer, 0, 256); |
JonFreeman | 4:67478861c670 | 479 | |
JonFreeman | 4:67478861c670 | 480 | // Jon's play with Write memory |
JonFreeman | 4:67478861c670 | 481 | qspiwr ((uint8_t*)MemInitString, WRITE_READ_ADDR2); |
JonFreeman | 4:67478861c670 | 482 | qspiwr ((uint8_t*)Ifound_String, WRITE_READ_ADDR3); |
JonFreeman | 4:67478861c670 | 483 | |
JonFreeman | 4:67478861c670 | 484 | qspird(ReadBuffer, 0, 256); // shows correct write of "Electric Locomotive Controller" after "Hello World !!!" |
JonFreeman | 4:67478861c670 | 485 | qspird(ReadBuffer, WRITE_READ_ADDR2, 250); |
JonFreeman | 4:67478861c670 | 486 | |
JonFreeman | 4:67478861c670 | 487 | qspird(ReadBuffer, WRITE_READ_ADDR3, 250); |
JonFreeman | 4:67478861c670 | 488 | pc.printf ("\r\r\r\n"); |
JonFreeman | 4:67478861c670 | 489 | qspiwr ((uint8_t*)"Today I have to pack the car full of all sorts of stuff including 7.25 gauge loco and take it up to Begbrook to show members of Bristol Society of Model and Experimental Engineers!", 2000); |
JonFreeman | 4:67478861c670 | 490 | qspird(ReadBuffer, 0, 4096); |
JonFreeman | 4:67478861c670 | 491 | |
JonFreeman | 4:67478861c670 | 492 | int pos = qspifindfree (ReadBuffer, 0); |
JonFreeman | 4:67478861c670 | 493 | pc.printf ("qspifindfree reports %d\r\n", pos); |
JonFreeman | 4:67478861c670 | 494 | */ |
JonFreeman | 4:67478861c670 | 495 | //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 | 496 | |
JonFreeman | 4:67478861c670 | 497 | pc.printf ("\r\r\r\n"); |
JonFreeman | 4:67478861c670 | 498 | #endif |
JonFreeman | 4:67478861c670 | 499 | |
JonFreeman | 4:67478861c670 | 500 | #ifdef SDCARD |
JonFreeman | 4:67478861c670 | 501 | uint8_t SD_state; |
JonFreeman | 4:67478861c670 | 502 | SD_state = sd.Init(); |
JonFreeman | 4:67478861c670 | 503 | if(SD_state != MSD_OK){ |
JonFreeman | 4:67478861c670 | 504 | if(SD_state == MSD_ERROR_SD_NOT_PRESENT){ |
JonFreeman | 4:67478861c670 | 505 | pc.printf("SD shall be inserted before running test\r\n"); |
JonFreeman | 4:67478861c670 | 506 | } else { |
JonFreeman | 4:67478861c670 | 507 | pc.printf("SD Initialization : FAIL.\r\n"); |
JonFreeman | 4:67478861c670 | 508 | } |
JonFreeman | 4:67478861c670 | 509 | pc.printf("SD Test Aborted.\r\n"); |
JonFreeman | 4:67478861c670 | 510 | } else { |
JonFreeman | 4:67478861c670 | 511 | pc.printf("SD Initialization : OK.\r\n"); |
JonFreeman | 4:67478861c670 | 512 | |
JonFreeman | 4:67478861c670 | 513 | SD_state = sd.Erase(BLOCK_START_ADDR, (BLOCK_START_ADDR + NUM_OF_BLOCKS - 1)); |
JonFreeman | 4:67478861c670 | 514 | |
JonFreeman | 4:67478861c670 | 515 | /* Wait until SD card is ready to use for new operation */ |
JonFreeman | 4:67478861c670 | 516 | while(sd.GetCardState() != SD_TRANSFER_OK){ |
JonFreeman | 4:67478861c670 | 517 | } |
JonFreeman | 4:67478861c670 | 518 | if (SD_state != MSD_OK){ |
JonFreeman | 4:67478861c670 | 519 | pc.printf("SD ERASE : FAILED.\r\n"); |
JonFreeman | 4:67478861c670 | 520 | pc.printf("SD Test Aborted.\r\n"); |
JonFreeman | 4:67478861c670 | 521 | } else { |
JonFreeman | 4:67478861c670 | 522 | pc.printf("SD ERASE : OK.\r\n"); |
JonFreeman | 4:67478861c670 | 523 | |
JonFreeman | 4:67478861c670 | 524 | /* Fill the buffer to write */ |
JonFreeman | 4:67478861c670 | 525 | Fill_Buffer(aTxBuffer, BUFFER_WORDS_SIZE, 0x2300); |
JonFreeman | 4:67478861c670 | 526 | |
JonFreeman | 4:67478861c670 | 527 | SD_state = sd.WriteBlocks(aTxBuffer, BLOCK_START_ADDR, NUM_OF_BLOCKS, 10000); |
JonFreeman | 4:67478861c670 | 528 | /* Wait until SD card is ready to use for new operation */ |
JonFreeman | 4:67478861c670 | 529 | while(sd.GetCardState() != SD_TRANSFER_OK){ |
JonFreeman | 4:67478861c670 | 530 | } |
JonFreeman | 4:67478861c670 | 531 | |
JonFreeman | 4:67478861c670 | 532 | if (SD_state != MSD_OK){ |
JonFreeman | 4:67478861c670 | 533 | pc.printf("SD WRITE : FAILED.\r\n"); |
JonFreeman | 4:67478861c670 | 534 | pc.printf("SD Test Aborted.\r\n"); |
JonFreeman | 4:67478861c670 | 535 | } else { |
JonFreeman | 4:67478861c670 | 536 | pc.printf("SD WRITE : OK.\r\n"); |
JonFreeman | 4:67478861c670 | 537 | |
JonFreeman | 4:67478861c670 | 538 | SD_state = sd.ReadBlocks(aRxBuffer, BLOCK_START_ADDR, NUM_OF_BLOCKS, 10000); |
JonFreeman | 4:67478861c670 | 539 | /* Wait until SD card is ready to use for new operation */ |
JonFreeman | 4:67478861c670 | 540 | while(sd.GetCardState() != SD_TRANSFER_OK){ |
JonFreeman | 4:67478861c670 | 541 | } |
JonFreeman | 4:67478861c670 | 542 | |
JonFreeman | 4:67478861c670 | 543 | if (SD_state != MSD_OK){ |
JonFreeman | 4:67478861c670 | 544 | pc.printf("SD READ : FAILED.\r\n"); |
JonFreeman | 4:67478861c670 | 545 | pc.printf("SD Test Aborted.\r\n"); |
JonFreeman | 4:67478861c670 | 546 | } else { |
JonFreeman | 4:67478861c670 | 547 | pc.printf("SD READ : OK.\r\n"); |
JonFreeman | 4:67478861c670 | 548 | if(Buffercmp(aTxBuffer, aRxBuffer, BUFFER_WORDS_SIZE) > 0){ |
JonFreeman | 4:67478861c670 | 549 | pc.printf("SD COMPARE : FAILED.\r\n"); |
JonFreeman | 4:67478861c670 | 550 | pc.printf("SD Test Aborted.\r\n"); |
JonFreeman | 4:67478861c670 | 551 | } else { |
JonFreeman | 4:67478861c670 | 552 | pc.printf("SD Test : OK.\r\n"); |
JonFreeman | 4:67478861c670 | 553 | pc.printf("SD can be removed.\r\n"); |
JonFreeman | 4:67478861c670 | 554 | } |
JonFreeman | 4:67478861c670 | 555 | } |
JonFreeman | 4:67478861c670 | 556 | } |
JonFreeman | 4:67478861c670 | 557 | } |
JonFreeman | 4:67478861c670 | 558 | } |
JonFreeman | 4:67478861c670 | 559 | pc.printf ("\r\n"); |
JonFreeman | 4:67478861c670 | 560 | #endif |
JonFreeman | 4:67478861c670 | 561 | |
JonFreeman | 4:67478861c670 | 562 | int qtr_sec = 0, seconds = 0, minutes = 0; |
JonFreeman | 4:67478861c670 | 563 | double electrical_power_Watt = 0.0; |
JonFreeman | 4:67478861c670 | 564 | ky_bd kybd_a, kybd_b; |
JonFreeman | 4:67478861c670 | 565 | memset (&kybd_a, 0, sizeof(kybd_a)); |
JonFreeman | 4:67478861c670 | 566 | memset (&kybd_b, 0, sizeof(kybd_b)); |
JonFreeman | 4:67478861c670 | 567 | |
JonFreeman | 4:67478861c670 | 568 | // spareio_d8.mode (PullUp); now output driving throttle servo |
JonFreeman | 4:67478861c670 | 569 | spareio_d9.mode (PullUp); |
JonFreeman | 4:67478861c670 | 570 | spareio_d10.mode(PullUp); |
JonFreeman | 4:67478861c670 | 571 | |
JonFreeman | 4:67478861c670 | 572 | Ticker tick250us; |
JonFreeman | 4:67478861c670 | 573 | |
JonFreeman | 4:67478861c670 | 574 | // Setup User Interrupt Vectors |
JonFreeman | 4:67478861c670 | 575 | mot1hall.fall (&ISR_mot1_hall_handler); |
JonFreeman | 4:67478861c670 | 576 | mot1hall.rise (&ISR_mot1_hall_handler); |
JonFreeman | 4:67478861c670 | 577 | mot2hall.fall (&ISR_mot2_hall_handler); |
JonFreeman | 4:67478861c670 | 578 | mot2hall.rise (&ISR_mot2_hall_handler); |
JonFreeman | 4:67478861c670 | 579 | mot3hall.fall (&ISR_mot3_hall_handler); |
JonFreeman | 4:67478861c670 | 580 | mot3hall.rise (&ISR_mot3_hall_handler); |
JonFreeman | 4:67478861c670 | 581 | mot4hall.fall (&ISR_mot4_hall_handler); |
JonFreeman | 4:67478861c670 | 582 | mot4hall.rise (&ISR_mot4_hall_handler); |
JonFreeman | 4:67478861c670 | 583 | |
JonFreeman | 4:67478861c670 | 584 | tick250us.attach_us (&ISR_current_reader, 250); // count 125 of these to trig 31.25ms |
JonFreeman | 4:67478861c670 | 585 | // tick32ms.attach_us (&ISR_tick_32ms, 32001); |
JonFreeman | 4:67478861c670 | 586 | // tick32ms.attach_us (&ISR_tick_32ms, 31250); // then count 8 pulses per 250ms |
JonFreeman | 4:67478861c670 | 587 | // tick250ms.attach_us (&ISR_tick_250ms, 250002); |
JonFreeman | 4:67478861c670 | 588 | pc.baud (9600); |
JonFreeman | 4:67478861c670 | 589 | // GfetT1 = 0; |
JonFreeman | 4:67478861c670 | 590 | // GfetT2 = 0; // two output bits for future use driving horns |
JonFreeman | 4:67478861c670 | 591 | if (f_r_switch) |
JonFreeman | 4:67478861c670 | 592 | slider.direction = FWD; // make decision from key switch position here |
JonFreeman | 4:67478861c670 | 593 | else |
JonFreeman | 4:67478861c670 | 594 | slider.direction = REV; // make decision from key switch position here |
JonFreeman | 4:67478861c670 | 595 | |
JonFreeman | 4:67478861c670 | 596 | // max_pwm_ticks = SystemCoreClock / (2 * PWM_HZ); // prescaler min value is 2, or so it would seem. SystemCoreClock returns 216000000 on F746NG board |
JonFreeman | 4:67478861c670 | 597 | maxv.period_ticks (MAX_PWM_TICKS + 1); // around 18 kHz |
JonFreeman | 4:67478861c670 | 598 | maxi.period_ticks (MAX_PWM_TICKS + 1); |
JonFreeman | 4:67478861c670 | 599 | set_I_limit (0.0); |
JonFreeman | 4:67478861c670 | 600 | set_V_limit (0.0); |
JonFreeman | 4:67478861c670 | 601 | |
JonFreeman | 4:67478861c670 | 602 | pc.printf ("Jon's Touch Screen Loco 2017 sytem starting up %s\r\n", slider.direction ? "Forward":"Reverse"); |
JonFreeman | 4:67478861c670 | 603 | uint8_t lcd_status = touch_screen.Init(lcd.GetXSize(), lcd.GetYSize()); |
JonFreeman | 4:67478861c670 | 604 | if (lcd_status != TS_OK) { |
JonFreeman | 4:67478861c670 | 605 | lcd.Clear(LCD_COLOR_RED); |
JonFreeman | 4:67478861c670 | 606 | lcd.SetBackColor(LCD_COLOR_RED); |
JonFreeman | 4:67478861c670 | 607 | lcd.SetTextColor(LCD_COLOR_WHITE); |
JonFreeman | 4:67478861c670 | 608 | lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE); |
JonFreeman | 4:67478861c670 | 609 | wait (20); |
JonFreeman | 4:67478861c670 | 610 | } else { |
JonFreeman | 4:67478861c670 | 611 | lcd.Clear(LCD_COLOR_DARKBLUE); |
JonFreeman | 4:67478861c670 | 612 | lcd.SetBackColor(LCD_COLOR_GREEN); |
JonFreeman | 4:67478861c670 | 613 | lcd.SetTextColor(LCD_COLOR_WHITE); |
JonFreeman | 4:67478861c670 | 614 | lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT OK", CENTER_MODE); |
JonFreeman | 4:67478861c670 | 615 | } |
JonFreeman | 4:67478861c670 | 616 | |
JonFreeman | 4:67478861c670 | 617 | lcd.SetFont(&Font16); |
JonFreeman | 4:67478861c670 | 618 | lcd.Clear(LCD_COLOR_LIGHTGRAY); |
JonFreeman | 4:67478861c670 | 619 | setup_buttons(); // draws buttons |
JonFreeman | 4:67478861c670 | 620 | |
JonFreeman | 4:67478861c670 | 621 | slider.oldpos = 0; |
JonFreeman | 4:67478861c670 | 622 | slider.loco_speed = 0.0; |
JonFreeman | 4:67478861c670 | 623 | slider.handbrake_effort = 0.1; |
JonFreeman | 4:67478861c670 | 624 | slider.position = MAX_POS - 2; // Low down in REGEN_BRAKE position - NOT to power-up in PARK |
JonFreeman | 4:67478861c670 | 625 | SliderGraphic (slider); // sets slider.state to value determined by slider.position |
JonFreeman | 4:67478861c670 | 626 | set_run_mode (REGEN_BRAKE); // sets slider.mode |
JonFreeman | 4:67478861c670 | 627 | |
JonFreeman | 4:67478861c670 | 628 | lcd.SetBackColor(LCD_COLOR_DARKBLUE); |
JonFreeman | 4:67478861c670 | 629 | |
JonFreeman | 4:67478861c670 | 630 | vm_set(); // Draw 3 analogue meter movements, speedo, voltmeter, ammeter |
JonFreeman | 4:67478861c670 | 631 | |
JonFreeman | 4:67478861c670 | 632 | #ifdef SDCARD |
JonFreeman | 4:67478861c670 | 633 | // mainSDtest(); |
JonFreeman | 4:67478861c670 | 634 | #endif |
JonFreeman | 4:67478861c670 | 635 | |
JonFreeman | 4:67478861c670 | 636 | // odometer_zero (); |
JonFreeman | 4:67478861c670 | 637 | // pc.printf ("Back from odometer_zero\r\n"); |
JonFreeman | 4:67478861c670 | 638 | double torque_req = 0.0; |
JonFreeman | 4:67478861c670 | 639 | bool toggle32ms = false; |
JonFreeman | 4:67478861c670 | 640 | // Main loop |
JonFreeman | 4:67478861c670 | 641 | extern void show_all_banks () ; |
JonFreeman | 4:67478861c670 | 642 | // show_all_banks (); |
JonFreeman | 4:67478861c670 | 643 | |
JonFreeman | 4:67478861c670 | 644 | while (1) { |
JonFreeman | 4:67478861c670 | 645 | |
JonFreeman | 4:67478861c670 | 646 | struct ky_bd * present_kybd, * previous_kybd; |
JonFreeman | 4:67478861c670 | 647 | bool sliderpress = false; |
JonFreeman | 4:67478861c670 | 648 | command_line_interpreter () ; // Do any actions from command line via usb link |
JonFreeman | 4:67478861c670 | 649 | stuff_to_do_every_250us () ; |
JonFreeman | 4:67478861c670 | 650 | |
JonFreeman | 4:67478861c670 | 651 | if (trigger_32ms == true) { // Stuff to do every 32 milli secs |
JonFreeman | 4:67478861c670 | 652 | trigger_32ms = false; |
JonFreeman | 4:67478861c670 | 653 | |
JonFreeman | 4:67478861c670 | 654 | // CALL THROTTLE HERE - why here ? Ah yes, this initiates servo pulse. Need steady stream of servo pulses even when nothing changes. |
JonFreeman | 4:67478861c670 | 655 | throttle (torque_req, 2.3); |
JonFreeman | 4:67478861c670 | 656 | |
JonFreeman | 4:67478861c670 | 657 | toggle32ms = !toggle32ms; |
JonFreeman | 4:67478861c670 | 658 | if (toggle32ms) { |
JonFreeman | 4:67478861c670 | 659 | present_kybd = &kybd_a; |
JonFreeman | 4:67478861c670 | 660 | previous_kybd = &kybd_b; |
JonFreeman | 4:67478861c670 | 661 | } else { |
JonFreeman | 4:67478861c670 | 662 | present_kybd = &kybd_b; |
JonFreeman | 4:67478861c670 | 663 | previous_kybd = &kybd_a; |
JonFreeman | 4:67478861c670 | 664 | } |
JonFreeman | 4:67478861c670 | 665 | read_keypresses (*present_kybd); |
JonFreeman | 4:67478861c670 | 666 | sliderpress = false; |
JonFreeman | 4:67478861c670 | 667 | slider.recalc_run = false; |
JonFreeman | 4:67478861c670 | 668 | int j = 0; |
JonFreeman | 4:67478861c670 | 669 | // if (present2->count > previous_kybd->count) pc.printf ("More presses\r\n"); |
JonFreeman | 4:67478861c670 | 670 | // if (present2->count < previous_kybd->count) pc.printf ("Fewer presses\r\n"); |
JonFreeman | 4:67478861c670 | 671 | if (present_kybd->count || previous_kybd->count) { // at least one key pressed this time or last time |
JonFreeman | 4:67478861c670 | 672 | int k; |
JonFreeman | 4:67478861c670 | 673 | double dbl; |
JonFreeman | 4:67478861c670 | 674 | // pc.printf ("Keys action may be required"); |
JonFreeman | 4:67478861c670 | 675 | // if key in present and ! in previous, found new key press to handle |
JonFreeman | 4:67478861c670 | 676 | // if key ! in present and in previous, found new key release to handle |
JonFreeman | 4:67478861c670 | 677 | if (inlist(*present_kybd, SLIDER)) { // Finger is on slider, so Update slider graphic here |
JonFreeman | 4:67478861c670 | 678 | sliderpress = true; |
JonFreeman | 4:67478861c670 | 679 | k = present_kybd->slider_y; // get position of finger on slider |
JonFreeman | 4:67478861c670 | 680 | if (slider.state == RUN && k != slider.position) // Finger has moved within RUN range |
JonFreeman | 4:67478861c670 | 681 | slider.recalc_run = true; |
JonFreeman | 4:67478861c670 | 682 | if (slider.state == RUN && k >= NEUTRAL_VAL) // Finger has moved from RUN to BRAKE range |
JonFreeman | 4:67478861c670 | 683 | slider.position = k = NEUTRAL_VAL; // kill drive for rapid reaction to braking |
JonFreeman | 4:67478861c670 | 684 | |
JonFreeman | 4:67478861c670 | 685 | else { // nice slow non-jerky glidey movement required |
JonFreeman | 4:67478861c670 | 686 | dbl = (double)(k - slider.position); |
JonFreeman | 4:67478861c670 | 687 | dbl /= 13.179; // Where did 13.179 come from ? |
JonFreeman | 4:67478861c670 | 688 | if (dbl < 0.0) |
JonFreeman | 4:67478861c670 | 689 | dbl -= 1.0; |
JonFreeman | 4:67478861c670 | 690 | if (dbl > 0.0) |
JonFreeman | 4:67478861c670 | 691 | dbl += 1.0; |
JonFreeman | 4:67478861c670 | 692 | slider.position += (int)dbl; |
JonFreeman | 4:67478861c670 | 693 | } |
JonFreeman | 4:67478861c670 | 694 | SliderGraphic (slider); // sets slider.state to value determined by slider.position |
JonFreeman | 4:67478861c670 | 695 | set_run_mode (slider.state); |
JonFreeman | 4:67478861c670 | 696 | draw_button_hilight (SLIDER, LCD_COLOR_YELLOW) ; |
JonFreeman | 4:67478861c670 | 697 | |
JonFreeman | 4:67478861c670 | 698 | if (slider.state == REGEN_BRAKE) { |
JonFreeman | 4:67478861c670 | 699 | double brake_effort = ((double)(slider.position - NEUTRAL_VAL) |
JonFreeman | 4:67478861c670 | 700 | / (double)(MAX_POS - NEUTRAL_VAL)); |
JonFreeman | 4:67478861c670 | 701 | // brake_effort normalised to range 0.0 to 1.0 |
JonFreeman | 4:67478861c670 | 702 | brake_effort *= 0.97; // upper limit to braking effort, observed effect before was quite fierce |
JonFreeman | 4:67478861c670 | 703 | pc.printf ("Brake effort %.2f\r\n", brake_effort); |
JonFreeman | 4:67478861c670 | 704 | /* set_pwm (brake_effort); */ |
JonFreeman | 4:67478861c670 | 705 | set_V_limit (sqrt(brake_effort)); // sqrt gives more linear feel to control |
JonFreeman | 4:67478861c670 | 706 | set_I_limit (1.0); |
JonFreeman | 4:67478861c670 | 707 | } |
JonFreeman | 4:67478861c670 | 708 | } else { // pc.printf ("Slider not touched\r\n"); |
JonFreeman | 4:67478861c670 | 709 | } |
JonFreeman | 4:67478861c670 | 710 | |
JonFreeman | 4:67478861c670 | 711 | j = 0; |
JonFreeman | 4:67478861c670 | 712 | while (j < present_kybd->count) { // handle new key presses |
JonFreeman | 4:67478861c670 | 713 | k = present_kybd->ky[j++].keynum; |
JonFreeman | 4:67478861c670 | 714 | if (inlist(*present_kybd, k)) { |
JonFreeman | 4:67478861c670 | 715 | switch (k) { // Here for auto-repeat type key behaviour |
JonFreeman | 4:67478861c670 | 716 | case 21: // key is 'voltmeter' |
JonFreeman | 4:67478861c670 | 717 | // set_V_limit (last_pwm * 1.002 + 0.001); |
JonFreeman | 4:67478861c670 | 718 | break; |
JonFreeman | 4:67478861c670 | 719 | case 22: // key is 'ammeter' |
JonFreeman | 4:67478861c670 | 720 | // set_V_limit (last_pwm * 0.99); |
JonFreeman | 4:67478861c670 | 721 | break; |
JonFreeman | 4:67478861c670 | 722 | } // endof switch (k) |
JonFreeman | 4:67478861c670 | 723 | } // endof if (inlist(*present2, k)) { |
JonFreeman | 4:67478861c670 | 724 | if (inlist(*present_kybd, k) && !inlist(*previous_kybd, k)) { |
JonFreeman | 4:67478861c670 | 725 | pc.printf ("Handle Press %d\r\n", k); |
JonFreeman | 4:67478861c670 | 726 | draw_button_hilight (k, LCD_COLOR_YELLOW) ; |
JonFreeman | 4:67478861c670 | 727 | switch (k) { // Handle new touch screen button presses here - single action per press, not autorepeat |
JonFreeman | 4:67478861c670 | 728 | case SPEEDO_BUT: // |
JonFreeman | 4:67478861c670 | 729 | pc.printf ("Speedometer key pressed %d\r\n", k); |
JonFreeman | 4:67478861c670 | 730 | break; |
JonFreeman | 4:67478861c670 | 731 | case VMETER_BUT: // |
JonFreeman | 4:67478861c670 | 732 | pc.printf ("Voltmeter key pressed %d\r\n", k); |
JonFreeman | 4:67478861c670 | 733 | break; |
JonFreeman | 4:67478861c670 | 734 | case AMETER_BUT: // |
JonFreeman | 4:67478861c670 | 735 | pc.printf ("Ammeter key pressed %d\r\n", k); |
JonFreeman | 4:67478861c670 | 736 | break; |
JonFreeman | 4:67478861c670 | 737 | default: |
JonFreeman | 4:67478861c670 | 738 | pc.printf ("Unhandled keypress %d\r\n", k); |
JonFreeman | 4:67478861c670 | 739 | break; |
JonFreeman | 4:67478861c670 | 740 | } // endof switch (button) |
JonFreeman | 4:67478861c670 | 741 | } |
JonFreeman | 4:67478861c670 | 742 | } // endof while - handle new key presses |
JonFreeman | 4:67478861c670 | 743 | j = 0; |
JonFreeman | 4:67478861c670 | 744 | while (j < previous_kybd->count) { // handle new key releases |
JonFreeman | 4:67478861c670 | 745 | k = previous_kybd->ky[j++].keynum; |
JonFreeman | 4:67478861c670 | 746 | if (inlist(*previous_kybd, k) && !inlist(*present_kybd, k)) { |
JonFreeman | 4:67478861c670 | 747 | pc.printf ("Handle Release %d\r\n", k); |
JonFreeman | 4:67478861c670 | 748 | draw_button_hilight (k, LCD_COLOR_DARKBLUE) ; |
JonFreeman | 4:67478861c670 | 749 | } |
JonFreeman | 4:67478861c670 | 750 | } // endof while - handle new key releases |
JonFreeman | 4:67478861c670 | 751 | } // endof at least one key pressed this time or last time |
JonFreeman | 4:67478861c670 | 752 | |
JonFreeman | 4:67478861c670 | 753 | if (sliderpress == false) { // need to glide dead-mans function towards neutral here |
JonFreeman | 4:67478861c670 | 754 | if (slider.position < NEUTRAL_VAL) { |
JonFreeman | 4:67478861c670 | 755 | slider.position += 1 + (NEUTRAL_VAL - slider.position) / DAMPER_DECAY; |
JonFreeman | 4:67478861c670 | 756 | SliderGraphic (slider); |
JonFreeman | 4:67478861c670 | 757 | slider.recalc_run = true; |
JonFreeman | 4:67478861c670 | 758 | } |
JonFreeman | 4:67478861c670 | 759 | } |
JonFreeman | 4:67478861c670 | 760 | |
JonFreeman | 4:67478861c670 | 761 | if (slider.recalc_run) { // range of slider.position in RUN mode is min_pos_() to NEUTRAL_VAL - 1 |
JonFreeman | 4:67478861c670 | 762 | slider.recalc_run = false; // All RUN power and pwm calcs done here |
JonFreeman | 4:67478861c670 | 763 | int b = slider.position; |
JonFreeman | 4:67478861c670 | 764 | // double torque_req; // now declared above to be used as parameter for throttle |
JonFreeman | 4:67478861c670 | 765 | if (b > NEUTRAL_VAL) |
JonFreeman | 4:67478861c670 | 766 | b = NEUTRAL_VAL; |
JonFreeman | 4:67478861c670 | 767 | if (b < MIN_POS) // if finger position is above top of slider limit |
JonFreeman | 4:67478861c670 | 768 | b = MIN_POS; |
JonFreeman | 4:67478861c670 | 769 | b = NEUTRAL_VAL - b; // now got integer going positive for increasing power demand |
JonFreeman | 4:67478861c670 | 770 | torque_req = (double) b; |
JonFreeman | 4:67478861c670 | 771 | torque_req /= (NEUTRAL_VAL - MIN_POS); // in range 0.0 to 1.0 |
JonFreeman | 4:67478861c670 | 772 | pc.printf ("torque_rec = %.3f, last_pwm = %.3f\r\n", torque_req, last_pwm); |
JonFreeman | 4:67478861c670 | 773 | set_I_limit (torque_req); |
JonFreeman | 4:67478861c670 | 774 | if (torque_req < 0.05) |
JonFreeman | 4:67478861c670 | 775 | set_V_limit (last_pwm / 2.0); |
JonFreeman | 4:67478861c670 | 776 | else { |
JonFreeman | 4:67478861c670 | 777 | if (last_pwm < 0.99) |
JonFreeman | 4:67478861c670 | 778 | set_V_limit (last_pwm + 0.05); // ramp voltage up rather than slam to max |
JonFreeman | 4:67478861c670 | 779 | } |
JonFreeman | 4:67478861c670 | 780 | } |
JonFreeman | 4:67478861c670 | 781 | } // endof doing 32ms stuff |
JonFreeman | 4:67478861c670 | 782 | |
JonFreeman | 4:67478861c670 | 783 | if (qtrsec_trig == true) { // do every quarter second stuff here |
JonFreeman | 4:67478861c670 | 784 | qtrsec_trig = false; |
JonFreeman | 4:67478861c670 | 785 | speed.qtr_sec_update (); |
JonFreeman | 4:67478861c670 | 786 | double speedmph = speed.MPH(), amps = 0.0 - read_ammeter(), volts = read_voltmeter(); |
JonFreeman | 4:67478861c670 | 787 | //static const double mph_2_mm_per_sec = 447.04; // exact |
JonFreeman | 4:67478861c670 | 788 | // double mm_travelled_in_qtrsec = speedmph * mph_2_mm_per_sec / 4.0; |
JonFreeman | 4:67478861c670 | 789 | slider.loco_speed = speedmph; |
JonFreeman | 4:67478861c670 | 790 | electrical_power_Watt = volts * amps; // visible throughout main |
JonFreeman | 4:67478861c670 | 791 | update_meters (speedmph, electrical_power_Watt, volts) ; // displays speed, volts and power (volts times amps) |
JonFreeman | 4:67478861c670 | 792 | led_grn = !led_grn; |
JonFreeman | 4:67478861c670 | 793 | if (slider.state == PARK) { |
JonFreeman | 4:67478861c670 | 794 | if (speedmph > LOCO_HANDBRAKE_ESCAPE_SPEED / 4.0) { |
JonFreeman | 4:67478861c670 | 795 | slider.handbrake_effort *= 1.1; |
JonFreeman | 4:67478861c670 | 796 | if (slider.handbrake_effort > 0.55) slider.handbrake_effort = 0.55; |
JonFreeman | 4:67478861c670 | 797 | set_run_mode (PARK); |
JonFreeman | 4:67478861c670 | 798 | pc.printf ("Handbrake slipping, effort %.2f\r\n", slider.handbrake_effort); |
JonFreeman | 4:67478861c670 | 799 | } |
JonFreeman | 4:67478861c670 | 800 | if (speedmph < 0.02) { |
JonFreeman | 4:67478861c670 | 801 | slider.handbrake_effort *= 0.9; |
JonFreeman | 4:67478861c670 | 802 | if (slider.handbrake_effort < 0.05) slider.handbrake_effort = 0.05; |
JonFreeman | 4:67478861c670 | 803 | set_run_mode (PARK); |
JonFreeman | 4:67478861c670 | 804 | pc.printf ("Handbrake not slipping, effort %.2f\r\n", slider.handbrake_effort); |
JonFreeman | 4:67478861c670 | 805 | } |
JonFreeman | 4:67478861c670 | 806 | } |
JonFreeman | 4:67478861c670 | 807 | qtr_sec++; |
JonFreeman | 4:67478861c670 | 808 | // Can do stuff once per second here |
JonFreeman | 4:67478861c670 | 809 | if(qtr_sec > 3) { |
JonFreeman | 4:67478861c670 | 810 | qtr_sec = 0; |
JonFreeman | 4:67478861c670 | 811 | seconds++; |
JonFreeman | 4:67478861c670 | 812 | if (seconds > 59) { |
JonFreeman | 4:67478861c670 | 813 | seconds = 0; |
JonFreeman | 4:67478861c670 | 814 | minutes++; |
JonFreeman | 4:67478861c670 | 815 | // do once per minute stuff here |
JonFreeman | 4:67478861c670 | 816 | } // fall back into once per second |
JonFreeman | 4:67478861c670 | 817 | #ifdef QSPI |
JonFreeman | 4:67478861c670 | 818 | //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 | 819 | if (!odometer_update (historic_distance, (uint16_t)electrical_power_Watt, (uint16_t)(volts * 500.0))) |
JonFreeman | 4:67478861c670 | 820 | pc.printf ("Probs with odometer_update"); |
JonFreeman | 4:67478861c670 | 821 | char dist[20]; |
JonFreeman | 4:67478861c670 | 822 | sprintf (dist, "%05d m", speed.metres_travelled()); |
JonFreeman | 4:67478861c670 | 823 | displaytext (236, 226, 2, dist); |
JonFreeman | 4:67478861c670 | 824 | #endif |
JonFreeman | 4:67478861c670 | 825 | #ifdef SDCARD |
JonFreeman | 4:67478861c670 | 826 | if(SD_state == MSD_OK) { |
JonFreeman | 4:67478861c670 | 827 | char dist[20]; |
JonFreeman | 4:67478861c670 | 828 | sprintf (dist, "%05d m", speed.metres_travelled()); |
JonFreeman | 4:67478861c670 | 829 | displaytext (236, 226, 2, dist); |
JonFreeman | 4:67478861c670 | 830 | update_SD_card (); // Buffers data for SD card, writes when buffer filled |
JonFreeman | 4:67478861c670 | 831 | } |
JonFreeman | 4:67478861c670 | 832 | #endif |
JonFreeman | 4:67478861c670 | 833 | // calc_motor_amps( mva); |
JonFreeman | 4:67478861c670 | 834 | } // endof if(qtr_sec > 3 |
JonFreeman | 4:67478861c670 | 835 | } // endof if (qtrsec_trig == true) { |
JonFreeman | 4:67478861c670 | 836 | } // endof while(1) main programme loop |
JonFreeman | 4:67478861c670 | 837 | } |
JonFreeman | 4:67478861c670 | 838 | |
JonFreeman | 4:67478861c670 | 839 | |
JonFreeman | 4:67478861c670 | 840 |