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

Committer:
JonFreeman
Date:
Tue May 01 08:34:36 2018 +0000
Revision:
5:21a8ac83142c
Parent:
4:67478861c670
Child:
6:57dc760effd4
Added servo throttle, odometer not complete, ready for trial run

Who changed what in which revision?

UserRevisionLine numberNew 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 5:21a8ac83142c 20 #include "AsyncSerial.hpp"
JonFreeman 5:21a8ac83142c 21 #include "Servo.h"
JonFreeman 4:67478861c670 22 #include "TS_DISCO_F746NG.h"
JonFreeman 4:67478861c670 23 #include "LCD_DISCO_F746NG.h"
JonFreeman 5:21a8ac83142c 24 #include <cctype>
JonFreeman 4:67478861c670 25
JonFreeman 4:67478861c670 26 LCD_DISCO_F746NG lcd;
JonFreeman 4:67478861c670 27 TS_DISCO_F746NG touch_screen;
JonFreeman 4:67478861c670 28
JonFreeman 5:21a8ac83142c 29 //FastPWM maxv (D12, 1),
JonFreeman 5:21a8ac83142c 30 // maxi (D11, 1); // pin, prescaler value
JonFreeman 5:21a8ac83142c 31 Serial pc (USBTX, USBRX); // AsyncSerial does not work here. Comms to 'PuTTY' or similar comms programme on pc
JonFreeman 4:67478861c670 32
JonFreeman 5:21a8ac83142c 33 DigitalOut reverse_pin (D7); // These pins no longer used to set mode and direction, now commands issued to com
JonFreeman 5:21a8ac83142c 34 DigitalOut forward_pin (D9); //was D6, these two decode to fwd, rev, regen_braking and park
JonFreeman 4:67478861c670 35
JonFreeman 5:21a8ac83142c 36 DigitalOut I_sink1 (D14); // a horn
JonFreeman 5:21a8ac83142c 37 DigitalOut I_sink2 (D15); // another horn
JonFreeman 5:21a8ac83142c 38 DigitalOut I_sink3 (D3);
JonFreeman 5:21a8ac83142c 39 DigitalOut I_sink4 (D4);
JonFreeman 5:21a8ac83142c 40 DigitalOut I_sink5 (D5);
JonFreeman 5:21a8ac83142c 41 DigitalOut led_grn (LED1); // the only on board user led
JonFreeman 4:67478861c670 42
JonFreeman 5:21a8ac83142c 43 DigitalIn f_r_switch (D2); // was D0, Reads position of centre-off ignition switch
JonFreeman 4:67478861c670 44 //DigitalIn spareio_d8 (D8);
JonFreeman 5:21a8ac83142c 45 //DigitalIn spareio_d9 (D9);
JonFreeman 4:67478861c670 46 DigitalIn spareio_d10 (D10); // D8, D9, D10 wired to jumper on pcb - not used to Apr 2017
JonFreeman 4:67478861c670 47
JonFreeman 4:67478861c670 48 AnalogIn ht_volts_ain (A0); // Jan 2017
JonFreeman 4:67478861c670 49 AnalogIn ht_amps_ain (A1); // Jan 2017
JonFreeman 5:21a8ac83142c 50 //AnalogIn spare_ain2 (A2);
JonFreeman 5:21a8ac83142c 51 //AnalogIn spare_ain3 (A3);
JonFreeman 4:67478861c670 52 //AnalogIn spare_ain4 (A4); // hardware on pcb for these 3 spare analogue inputs - not used to Apr 2017
JonFreeman 4:67478861c670 53 //AnalogIn spare_ain5 (A5); // causes display flicker !
JonFreeman 5:21a8ac83142c 54
JonFreeman 5:21a8ac83142c 55
JonFreeman 5:21a8ac83142c 56 AsyncSerial com (A4, A5); // Com port to opto isolators on Twin BLDC Controller boards
JonFreeman 5:21a8ac83142c 57 //AsyncSerial ir (D1, D0); // Second port does work, but gives the old broken-up display flicker nonsense problem
JonFreeman 4:67478861c670 58
JonFreeman 4:67478861c670 59 /*
JonFreeman 4:67478861c670 60 Speed now read via opto serial ports
JonFreeman 5:21a8ac83142c 61 */
JonFreeman 4:67478861c670 62
JonFreeman 5:21a8ac83142c 63 Servo servo1 (D6); // Now used to adjust Honda speed
JonFreeman 5:21a8ac83142c 64
JonFreeman 4:67478861c670 65 extern bool odometer_zero () ; // Returns true on success
JonFreeman 4:67478861c670 66 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 67
JonFreeman 4:67478861c670 68 extern int get_button_press (struct point & pt) ;
JonFreeman 4:67478861c670 69 extern void displaytext (int x, int y, const int font, uint32_t BCol, uint32_t TCol, char * txt) ;
JonFreeman 4:67478861c670 70 extern void displaytext (int x, int y, const int font, char * txt) ;
JonFreeman 4:67478861c670 71 extern void displaytext (int x, int y, char * txt) ;
JonFreeman 4:67478861c670 72 extern void setup_buttons () ;
JonFreeman 4:67478861c670 73 extern void draw_numeric_keypad (int colour) ;
JonFreeman 4:67478861c670 74 extern void draw_button_hilight (int bu, int colour) ;
JonFreeman 4:67478861c670 75 extern void read_presses (int * a) ;
JonFreeman 4:67478861c670 76 extern void read_keypresses (struct ky_bd & a) ;
JonFreeman 4:67478861c670 77 extern void SliderGraphic (struct slide & q) ;
JonFreeman 4:67478861c670 78 extern void vm_set () ;
JonFreeman 4:67478861c670 79 extern void update_meters (double, double, double) ;
JonFreeman 4:67478861c670 80
JonFreeman 4:67478861c670 81 static const int
JonFreeman 4:67478861c670 82 DAMPER_DECAY = 42, // Small num -> fast 'viscous damper' on dead-mans function with finger removed from panel
JonFreeman 4:67478861c670 83 MAF_PTS = 140, // Moving Average Filter points. Filters reduce noise on volatage and current readings
JonFreeman 4:67478861c670 84 FWD = 0,
JonFreeman 4:67478861c670 85 REV = ~FWD;
JonFreeman 4:67478861c670 86
JonFreeman 4:67478861c670 87 //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 88 struct slide slider ;
JonFreeman 4:67478861c670 89
adustm 0:99e26e18b424 90
JonFreeman 4:67478861c670 91 int V_maf[MAF_PTS + 2], I_maf[MAF_PTS + 2], maf_ptr = 0; // ********* These should be uint16_t
JonFreeman 5:21a8ac83142c 92 uint32_t sys_timer_32Hz = 0;
JonFreeman 5:21a8ac83142c 93 double last_V = 0.0, last_I = 0.0, recent_distance = 0.0;
JonFreeman 4:67478861c670 94
JonFreeman 4:67478861c670 95 bool qtrsec_trig = false;
JonFreeman 4:67478861c670 96 bool trigger_current_read = false;
JonFreeman 4:67478861c670 97 volatile bool trigger_32ms = false;
JonFreeman 4:67478861c670 98
JonFreeman 5:21a8ac83142c 99 class speed_2018
JonFreeman 4:67478861c670 100 {
JonFreeman 5:21a8ac83142c 101 static const int SPEED_AVE_PTS = 5; // AVE_PTS - points in moving average filters
JonFreeman 5:21a8ac83142c 102 uint32_t speed_maf_mem [(SPEED_AVE_PTS + 1) * 2][NUMBER_OF_MOTORS],
JonFreeman 5:21a8ac83142c 103 axle_total [4],
JonFreeman 5:21a8ac83142c 104 mafptr;
JonFreeman 5:21a8ac83142c 105 double average_rpm_out;
JonFreeman 4:67478861c670 106 public:
JonFreeman 5:21a8ac83142c 107 speed_2018 () { // Constructor
JonFreeman 4:67478861c670 108 memset(speed_maf_mem, 0, sizeof(speed_maf_mem));
JonFreeman 5:21a8ac83142c 109 axle_total[0] = axle_total[1] = axle_total[2] = axle_total[3] = 0;
JonFreeman 4:67478861c670 110 mafptr = 0;
JonFreeman 5:21a8ac83142c 111 average_rpm_out = 0.0;
JonFreeman 5:21a8ac83142c 112 }
JonFreeman 5:21a8ac83142c 113 void rpm_update(struct parameters & a) ;
JonFreeman 5:21a8ac83142c 114 double mph () ;
JonFreeman 4:67478861c670 115 }
JonFreeman 5:21a8ac83142c 116 speed2 ;
JonFreeman 4:67478861c670 117
JonFreeman 5:21a8ac83142c 118 double speed_2018::mph () {
JonFreeman 5:21a8ac83142c 119 int t[4] = {0,0,0,0};
JonFreeman 5:21a8ac83142c 120 for (int i = 0; i < SPEED_AVE_PTS; i++) {
JonFreeman 5:21a8ac83142c 121 t[0] += speed_maf_mem[i][0];
JonFreeman 5:21a8ac83142c 122 t[1] += speed_maf_mem[i][1];
JonFreeman 5:21a8ac83142c 123 t[2] += speed_maf_mem[i][2];
JonFreeman 5:21a8ac83142c 124 t[3] += speed_maf_mem[i][3];
JonFreeman 4:67478861c670 125 }
JonFreeman 5:21a8ac83142c 126 int j = 0;
JonFreeman 5:21a8ac83142c 127 for (int i = 0; i < 4; i++) {
JonFreeman 5:21a8ac83142c 128 j += t[i];
JonFreeman 5:21a8ac83142c 129 axle_total[i] = t[i];
JonFreeman 5:21a8ac83142c 130 }
JonFreeman 5:21a8ac83142c 131 return (rpm2mph * ((double) j) / (SPEED_AVE_PTS * 4));
JonFreeman 4:67478861c670 132 }
JonFreeman 4:67478861c670 133
JonFreeman 5:21a8ac83142c 134 void speed_2018::rpm_update(struct parameters & a) { // Puts new readings into mem
JonFreeman 5:21a8ac83142c 135 if (a.gp_i == 0) {
JonFreeman 5:21a8ac83142c 136 speed_maf_mem [mafptr][0] = (uint32_t)a.dbl[0];
JonFreeman 5:21a8ac83142c 137 speed_maf_mem [mafptr][1] = (uint32_t)a.dbl[1];
JonFreeman 4:67478861c670 138 }
JonFreeman 5:21a8ac83142c 139 else {
JonFreeman 5:21a8ac83142c 140 speed_maf_mem [mafptr][2] = (uint32_t)a.dbl[0];
JonFreeman 5:21a8ac83142c 141 speed_maf_mem [mafptr][3] = (uint32_t)a.dbl[1];
JonFreeman 5:21a8ac83142c 142 mafptr++;
JonFreeman 5:21a8ac83142c 143 if (mafptr >= SPEED_AVE_PTS)
JonFreeman 5:21a8ac83142c 144 mafptr = 0;
JonFreeman 4:67478861c670 145 }
JonFreeman 4:67478861c670 146 }
JonFreeman 4:67478861c670 147
JonFreeman 5:21a8ac83142c 148
JonFreeman 5:21a8ac83142c 149 void rpm_push (struct parameters & a) { // Latest RPM reports from Dual BLDC Motor Controllers arrive here
JonFreeman 5:21a8ac83142c 150 speed2.rpm_update (a);
JonFreeman 5:21a8ac83142c 151 // pc.printf ("RPM%d %d, mph %.1f\r\n", (int)a.dbl[0], (int)a.dbl[1], speed2.mph());
JonFreeman 4:67478861c670 152 }
adustm 0:99e26e18b424 153
JonFreeman 4:67478861c670 154
JonFreeman 4:67478861c670 155
JonFreeman 4:67478861c670 156 void set_V_limit (double p) // Sets max motor voltage
JonFreeman 4:67478861c670 157 {
JonFreeman 4:67478861c670 158 if (p < 0.0)
JonFreeman 4:67478861c670 159 p = 0.0;
JonFreeman 4:67478861c670 160 if (p > 1.0)
JonFreeman 4:67478861c670 161 p = 1.0;
JonFreeman 5:21a8ac83142c 162 last_V = p;
JonFreeman 5:21a8ac83142c 163 com.printf ("v%d\r", (int)(p * 99.0));
JonFreeman 5:21a8ac83142c 164 // p *= 0.95; // need limit, ffi see MCP1630 data
JonFreeman 5:21a8ac83142c 165 // p = 1.0 - p; // because pwm is wrong way up
JonFreeman 5:21a8ac83142c 166 // maxv.pulsewidth_ticks ((int)(p * MAX_PWM_TICKS)); // PWM output on pin D12 inverted motor pwm
JonFreeman 4:67478861c670 167 }
JonFreeman 4:67478861c670 168
JonFreeman 4:67478861c670 169 void set_I_limit (double p) // Sets max motor current
JonFreeman 4:67478861c670 170 {
JonFreeman 5:21a8ac83142c 171 // int a;
JonFreeman 4:67478861c670 172 if (p < 0.0)
JonFreeman 4:67478861c670 173 p = 0.0;
JonFreeman 4:67478861c670 174 if (p > 1.0)
JonFreeman 4:67478861c670 175 p = 1.0;
JonFreeman 5:21a8ac83142c 176 last_I = p; // New 30/4/2018 ; no use for this yet, included to be consistent with V
JonFreeman 5:21a8ac83142c 177 com.printf ("i%d\r", (int)(p * 99.0));
JonFreeman 5:21a8ac83142c 178 // a = (int)(p * MAX_PWM_TICKS);
JonFreeman 5:21a8ac83142c 179 // if (a > MAX_PWM_TICKS)
JonFreeman 5:21a8ac83142c 180 // a = MAX_PWM_TICKS;
JonFreeman 5:21a8ac83142c 181 // if (a < 0)
JonFreeman 5:21a8ac83142c 182 // a = 0;
JonFreeman 5:21a8ac83142c 183 // maxi.pulsewidth_ticks (a); // PWM output on pin D12 inverted motor pwm
JonFreeman 4:67478861c670 184 }
JonFreeman 4:67478861c670 185
JonFreeman 4:67478861c670 186 double read_ammeter ()
JonFreeman 4:67478861c670 187 {
JonFreeman 4:67478861c670 188 int a = 0;
JonFreeman 4:67478861c670 189 for (int b = 0; b < MAF_PTS; b++)
JonFreeman 4:67478861c670 190 a += I_maf[b];
JonFreeman 4:67478861c670 191 a /= MAF_PTS;
JonFreeman 4:67478861c670 192 double i = (double) a;
JonFreeman 4:67478861c670 193 return (i * 95.0 / 32768.0) - 95.0 + 0.46; // fiddled to suit current module
JonFreeman 4:67478861c670 194 }
JonFreeman 4:67478861c670 195
JonFreeman 4:67478861c670 196 double read_voltmeter ()
JonFreeman 4:67478861c670 197 {
JonFreeman 4:67478861c670 198 int a = 0;
JonFreeman 4:67478861c670 199 for (int b = 0; b < MAF_PTS; b++)
JonFreeman 4:67478861c670 200 a += V_maf[b];
JonFreeman 4:67478861c670 201 a /= MAF_PTS;
JonFreeman 5:21a8ac83142c 202 double v = (double) a;
JonFreeman 5:21a8ac83142c 203 // return (v / 940.0) + 0.3; // fiddled to suit resistor values
JonFreeman 5:21a8ac83142c 204 return (v / 932.0) + 0.0; // fiddled to suit resistor values
JonFreeman 4:67478861c670 205 }
JonFreeman 4:67478861c670 206
JonFreeman 4:67478861c670 207 // Interrupt Service Routines
JonFreeman 4:67478861c670 208
JonFreeman 4:67478861c670 209 void ISR_current_reader (void) // FIXED at 250us
JonFreeman 4:67478861c670 210 {
JonFreeman 4:67478861c670 211 static int ms32 = 0, ms250 = 0;
JonFreeman 4:67478861c670 212 trigger_current_read = true; // every 250us, i.e. 4kHz NOTE only sets trigger here, readings taken in main loop
JonFreeman 4:67478861c670 213 ms32++;
JonFreeman 5:21a8ac83142c 214 if (ms32 > 124) { // 31.25ms, not 32ms, is 32Hz
JonFreeman 4:67478861c670 215 ms32 = 0;
JonFreeman 5:21a8ac83142c 216 sys_timer_32Hz++; // , usable anywhere as general measure of elapsed time
JonFreeman 4:67478861c670 217 trigger_32ms = true;
JonFreeman 4:67478861c670 218 ms250++;
JonFreeman 4:67478861c670 219 if (ms250 > 7) {
JonFreeman 4:67478861c670 220 ms250 = 0;
JonFreeman 4:67478861c670 221 qtrsec_trig = true;
JonFreeman 4:67478861c670 222 }
JonFreeman 4:67478861c670 223 }
JonFreeman 4:67478861c670 224 }
JonFreeman 4:67478861c670 225
JonFreeman 4:67478861c670 226 // End of Interrupt Service Routines
JonFreeman 4:67478861c670 227
JonFreeman 4:67478861c670 228
JonFreeman 4:67478861c670 229 bool inlist (struct ky_bd & a, int key)
JonFreeman 4:67478861c670 230 {
JonFreeman 4:67478861c670 231 int i = 0;
JonFreeman 4:67478861c670 232 while (i < a.count) {
JonFreeman 4:67478861c670 233 if (key == a.ky[i].keynum)
JonFreeman 4:67478861c670 234 return true;
JonFreeman 4:67478861c670 235 i++;
JonFreeman 4:67478861c670 236 }
JonFreeman 4:67478861c670 237 return false;
JonFreeman 4:67478861c670 238 }
JonFreeman 4:67478861c670 239
JonFreeman 4:67478861c670 240
JonFreeman 4:67478861c670 241 void stuff_to_do_every_250us () // Take readings of system voltage and current
JonFreeman 4:67478861c670 242 {
JonFreeman 4:67478861c670 243 if (!trigger_current_read)
JonFreeman 4:67478861c670 244 return;
JonFreeman 4:67478861c670 245 trigger_current_read = false;
JonFreeman 5:21a8ac83142c 246 int ch;
JonFreeman 5:21a8ac83142c 247 ch++;
JonFreeman 4:67478861c670 248 I_maf[maf_ptr] = ht_amps_ain.read_u16();
JonFreeman 4:67478861c670 249 V_maf[maf_ptr] = ht_volts_ain.read_u16();
JonFreeman 4:67478861c670 250 maf_ptr++;
JonFreeman 4:67478861c670 251 if (maf_ptr > MAF_PTS - 1)
JonFreeman 4:67478861c670 252 maf_ptr = 0;
JonFreeman 4:67478861c670 253 }
JonFreeman 4:67478861c670 254
JonFreeman 4:67478861c670 255 void set_run_mode (int mode)
JonFreeman 4:67478861c670 256 { // NOTE Nov 2017 - Handbrake not implemented
JonFreeman 4:67478861c670 257 if (mode == HANDBRAKE_SLIPPING) slider.handbrake_slipping = true;
JonFreeman 4:67478861c670 258 else slider.handbrake_slipping = false;
JonFreeman 4:67478861c670 259 switch (mode) {
JonFreeman 4:67478861c670 260 // STATES, INACTIVE, RUN, NEUTRAL_DRIFT, REGEN_BRAKE, PARK};
JonFreeman 4:67478861c670 261 // case HANDBRAKE_SLIPPING:
JonFreeman 4:67478861c670 262 // break;
JonFreeman 4:67478861c670 263 case PARK: // PARKED new rom code IS now finished.
JonFreeman 5:21a8ac83142c 264 // forward_pin = 0;
JonFreeman 5:21a8ac83142c 265 // reverse_pin = 0;
JonFreeman 4:67478861c670 266 slider.state = mode;
JonFreeman 4:67478861c670 267 set_V_limit (0.075); // was 0.1
JonFreeman 4:67478861c670 268 set_I_limit (slider.handbrake_effort);
JonFreeman 5:21a8ac83142c 269 // char tmp[16];
JonFreeman 5:21a8ac83142c 270 // sprintf (tmp, "vi7 %d\r", (int)(slider.handbrake_effort * 99.0));
JonFreeman 5:21a8ac83142c 271 // com.printf ("%s", tmp);
JonFreeman 4:67478861c670 272 break;
JonFreeman 4:67478861c670 273 case REGEN_BRAKE: // BRAKING, pwm affects degree
JonFreeman 5:21a8ac83142c 274 com.printf ("rb\r");
JonFreeman 5:21a8ac83142c 275 // forward_pin = 1;
JonFreeman 5:21a8ac83142c 276 // reverse_pin = 1;
JonFreeman 4:67478861c670 277 slider.state = mode;
JonFreeman 4:67478861c670 278 break;
JonFreeman 4:67478861c670 279 case NEUTRAL_DRIFT:
JonFreeman 4:67478861c670 280 slider.state = mode;
JonFreeman 4:67478861c670 281 set_I_limit (0.0); // added after first test runs, looking for cause of mechanical startup snatch
JonFreeman 4:67478861c670 282 set_V_limit (0.0); // added after first test runs, looking for cause of mechanical startup snatch
JonFreeman 4:67478861c670 283 break;
JonFreeman 4:67478861c670 284 case RUN:
JonFreeman 4:67478861c670 285 if (slider.direction) {
JonFreeman 5:21a8ac83142c 286 com.printf ("fw\r");
JonFreeman 5:21a8ac83142c 287 // forward_pin = 0;
JonFreeman 5:21a8ac83142c 288 // reverse_pin = 1;
JonFreeman 4:67478861c670 289 } else {
JonFreeman 5:21a8ac83142c 290 com.printf ("re\r");
JonFreeman 5:21a8ac83142c 291 // forward_pin = 1;
JonFreeman 5:21a8ac83142c 292 // reverse_pin = 0;
JonFreeman 4:67478861c670 293 }
JonFreeman 4:67478861c670 294 slider.state = mode;
JonFreeman 4:67478861c670 295 break;
JonFreeman 4:67478861c670 296 default:
JonFreeman 4:67478861c670 297 break;
JonFreeman 4:67478861c670 298 }
JonFreeman 4:67478861c670 299 }
JonFreeman 4:67478861c670 300
JonFreeman 4:67478861c670 301
JonFreeman 5:21a8ac83142c 302 void throttle (double p) { // New Apr 2018 ; servo adjusts throttle lever on Honda GX120
JonFreeman 5:21a8ac83142c 303 const double THR_MAX = 0.92;
JonFreeman 5:21a8ac83142c 304 const double THR_MIN = 0.09;
JonFreeman 5:21a8ac83142c 305 const double RANGE = THR_MAX - THR_MIN;
JonFreeman 5:21a8ac83142c 306 if (p > 1.0)
JonFreeman 5:21a8ac83142c 307 p = 1.0;
JonFreeman 5:21a8ac83142c 308 if (p < 0.0)
JonFreeman 5:21a8ac83142c 309 p = 0.0;
JonFreeman 5:21a8ac83142c 310 // p = 1.0 - p; // if direction needs swapping
JonFreeman 5:21a8ac83142c 311 p *= RANGE;
JonFreeman 5:21a8ac83142c 312 p += THR_MIN;
JonFreeman 5:21a8ac83142c 313 servo1 = p;
adustm 0:99e26e18b424 314 }
adustm 0:99e26e18b424 315
JonFreeman 5:21a8ac83142c 316
JonFreeman 5:21a8ac83142c 317 extern void setup_pccom () ;
JonFreeman 5:21a8ac83142c 318 extern void setup_lococom () ;
JonFreeman 5:21a8ac83142c 319 extern void clicore (struct parameters & a) ;
JonFreeman 5:21a8ac83142c 320 extern struct parameters pccom, lococom;
JonFreeman 4:67478861c670 321
JonFreeman 4:67478861c670 322 int main()
JonFreeman 4:67478861c670 323 {
JonFreeman 4:67478861c670 324 #ifdef QSPI
JonFreeman 4:67478861c670 325
JonFreeman 4:67478861c670 326 extern int qspifindfree (uint8_t* dest, uint32_t addr) ;
JonFreeman 4:67478861c670 327 extern int ask_QSPI_OK () ;
JonFreeman 4:67478861c670 328 extern bool qspimemcheck () ;
JonFreeman 4:67478861c670 329 extern int qspiinit () ;
JonFreeman 4:67478861c670 330 int qspi_ok = ask_QSPI_OK ();
JonFreeman 4:67478861c670 331 //extern int qspieraseblock (uint32_t addr) ;
JonFreeman 4:67478861c670 332 //extern int qspiwr (uint8_t* src, uint32_t addr) ;
JonFreeman 4:67478861c670 333 //extern int qspiwr (uint8_t* src, uint32_t addr, uint32_t len) ;
JonFreeman 4:67478861c670 334 //extern int qspird (uint8_t* dest, uint32_t addr, uint32_t len) ;
JonFreeman 4:67478861c670 335
JonFreeman 4:67478861c670 336 //#define BUFFER_SIZE ((uint32_t)32)
JonFreeman 4:67478861c670 337 //#define QSPI_BUFFER_SIZE ((uint32_t)4270) // Big enough for 4096 byte block
JonFreeman 4:67478861c670 338 //#define WRITE_READ_ADDR ((uint32_t)0x0050)
JonFreeman 4:67478861c670 339 //#define WRITE_READ_ADDR ((uint32_t)0x0010)
JonFreeman 4:67478861c670 340 //#define WRITE_READ_ADDR2 ((uint32_t)0x0020)
JonFreeman 4:67478861c670 341 //#define WRITE_READ_ADDR3 ((uint32_t)0x4030)
JonFreeman 4:67478861c670 342 //#define QSPI_BASE_ADDR ((uint32_t)0x90000000)
JonFreeman 4:67478861c670 343
JonFreeman 4:67478861c670 344 // 123456789012345
JonFreeman 4:67478861c670 345 // uint8_t WriteBuffer[QSPI_BUFFER_SIZE] = "Hello World !!!\0";
JonFreeman 4:67478861c670 346 // uint8_t ReadBuffer[QSPI_BUFFER_SIZE];
JonFreeman 4:67478861c670 347 // const uint8_t MemInitString[] = "Electric Locomotive Controller - Jon Freeman B. Eng. Hons - November 2017\0";
JonFreeman 4:67478861c670 348 // const uint8_t Ifound_String[] = "I found the man sir, god I wish I hadn't!\0";
JonFreeman 4:67478861c670 349
JonFreeman 4:67478861c670 350 // pc.printf ("[%s]\r\n", MemInitString);
JonFreeman 4:67478861c670 351 // pc.printf ("[%s]\r\n", Ifound_String);
JonFreeman 4:67478861c670 352 // pc.printf("\n\nQSPI demo started\r\n");
JonFreeman 4:67478861c670 353
JonFreeman 4:67478861c670 354 // Check initialization
JonFreeman 4:67478861c670 355 if (qspiinit() != qspi_ok)
JonFreeman 4:67478861c670 356 error("Initialization FAILED\r\n");
JonFreeman 4:67478861c670 357 else
JonFreeman 4:67478861c670 358 pc.printf("Initialization PASSED\r\n");
JonFreeman 4:67478861c670 359
JonFreeman 4:67478861c670 360 // Check memory informations
JonFreeman 4:67478861c670 361 if (!qspimemcheck ())
JonFreeman 4:67478861c670 362 pc.printf ("Problem with qspimemcheck\r\n");
JonFreeman 4:67478861c670 363 /* // Erase memory
JonFreeman 4:67478861c670 364 qspieraseblock (WRITE_READ_ADDR);
JonFreeman 4:67478861c670 365 qspieraseblock (WRITE_READ_ADDR2);
JonFreeman 4:67478861c670 366 qspieraseblock (WRITE_READ_ADDR3);
JonFreeman 4:67478861c670 367 qspieraseblock (0x02000);
JonFreeman 4:67478861c670 368 // Write memory
JonFreeman 4:67478861c670 369 qspiwr(WriteBuffer, WRITE_READ_ADDR);
JonFreeman 4:67478861c670 370 qspird(ReadBuffer, WRITE_READ_ADDR, 20);
JonFreeman 4:67478861c670 371 qspiwr((uint8_t*)"Oh what a joy it is.", 0x02000);
JonFreeman 4:67478861c670 372 qspird(ReadBuffer, 0x02000, 20);
JonFreeman 4:67478861c670 373 qspieraseblock (0x02000);
JonFreeman 4:67478861c670 374 */ // Read memory
JonFreeman 4:67478861c670 375 // if (qspi.Read(ReadBuffer, WRITE_READ_ADDR, 11) != QSPI_OK)
JonFreeman 4:67478861c670 376 /* qspird(ReadBuffer, WRITE_READ_ADDR, 256);
JonFreeman 4:67478861c670 377 qspird(ReadBuffer, WRITE_READ_ADDR + 1, 256);
JonFreeman 4:67478861c670 378 qspird(ReadBuffer, 0, 256);
JonFreeman 4:67478861c670 379
JonFreeman 4:67478861c670 380 // Jon's play with Write memory
JonFreeman 4:67478861c670 381 qspiwr ((uint8_t*)MemInitString, WRITE_READ_ADDR2);
JonFreeman 4:67478861c670 382 qspiwr ((uint8_t*)Ifound_String, WRITE_READ_ADDR3);
JonFreeman 4:67478861c670 383
JonFreeman 4:67478861c670 384 qspird(ReadBuffer, 0, 256); // shows correct write of "Electric Locomotive Controller" after "Hello World !!!"
JonFreeman 4:67478861c670 385 qspird(ReadBuffer, WRITE_READ_ADDR2, 250);
JonFreeman 4:67478861c670 386
JonFreeman 4:67478861c670 387 qspird(ReadBuffer, WRITE_READ_ADDR3, 250);
JonFreeman 4:67478861c670 388 pc.printf ("\r\r\r\n");
JonFreeman 4:67478861c670 389 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 390 qspird(ReadBuffer, 0, 4096);
JonFreeman 4:67478861c670 391
JonFreeman 4:67478861c670 392 int pos = qspifindfree (ReadBuffer, 0);
JonFreeman 4:67478861c670 393 pc.printf ("qspifindfree reports %d\r\n", pos);
JonFreeman 4:67478861c670 394 */
JonFreeman 4:67478861c670 395 //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 396
JonFreeman 4:67478861c670 397 pc.printf ("\r\r\r\n");
JonFreeman 4:67478861c670 398 #endif
JonFreeman 4:67478861c670 399
JonFreeman 4:67478861c670 400
JonFreeman 4:67478861c670 401 int qtr_sec = 0, seconds = 0, minutes = 0;
JonFreeman 4:67478861c670 402 double electrical_power_Watt = 0.0;
JonFreeman 4:67478861c670 403 ky_bd kybd_a, kybd_b;
JonFreeman 4:67478861c670 404 memset (&kybd_a, 0, sizeof(kybd_a));
JonFreeman 4:67478861c670 405 memset (&kybd_b, 0, sizeof(kybd_b));
JonFreeman 4:67478861c670 406
JonFreeman 4:67478861c670 407 // spareio_d8.mode (PullUp); now output driving throttle servo
JonFreeman 5:21a8ac83142c 408 // spareio_d9.mode (PullUp);
JonFreeman 4:67478861c670 409 spareio_d10.mode(PullUp);
JonFreeman 4:67478861c670 410
JonFreeman 4:67478861c670 411 Ticker tick250us;
JonFreeman 4:67478861c670 412
JonFreeman 4:67478861c670 413 // Setup User Interrupt Vectors
JonFreeman 4:67478861c670 414 tick250us.attach_us (&ISR_current_reader, 250); // count 125 of these to trig 31.25ms
JonFreeman 4:67478861c670 415 // tick32ms.attach_us (&ISR_tick_32ms, 32001);
JonFreeman 4:67478861c670 416 // tick32ms.attach_us (&ISR_tick_32ms, 31250); // then count 8 pulses per 250ms
JonFreeman 4:67478861c670 417 // tick250ms.attach_us (&ISR_tick_250ms, 250002);
JonFreeman 4:67478861c670 418 pc.baud (9600);
JonFreeman 5:21a8ac83142c 419 com.baud (19200);
JonFreeman 5:21a8ac83142c 420 // ir.baud (1200);
JonFreeman 5:21a8ac83142c 421
JonFreeman 5:21a8ac83142c 422 I_sink1 = 0; // turn outputs off
JonFreeman 5:21a8ac83142c 423 I_sink2 = 0;
JonFreeman 5:21a8ac83142c 424 I_sink3 = 0;
JonFreeman 5:21a8ac83142c 425 I_sink4 = 0;
JonFreeman 5:21a8ac83142c 426 I_sink5 = 0;
JonFreeman 4:67478861c670 427 if (f_r_switch)
JonFreeman 4:67478861c670 428 slider.direction = FWD; // make decision from key switch position here
JonFreeman 4:67478861c670 429 else
JonFreeman 4:67478861c670 430 slider.direction = REV; // make decision from key switch position here
JonFreeman 4:67478861c670 431
JonFreeman 4:67478861c670 432 // max_pwm_ticks = SystemCoreClock / (2 * PWM_HZ); // prescaler min value is 2, or so it would seem. SystemCoreClock returns 216000000 on F746NG board
JonFreeman 5:21a8ac83142c 433 // maxv.period_ticks (MAX_PWM_TICKS + 1); // around 18 kHz
JonFreeman 5:21a8ac83142c 434 // maxi.period_ticks (MAX_PWM_TICKS + 1);
JonFreeman 4:67478861c670 435 set_I_limit (0.0);
JonFreeman 4:67478861c670 436 set_V_limit (0.0);
JonFreeman 5:21a8ac83142c 437 if (slider.direction)
JonFreeman 5:21a8ac83142c 438 com.printf ("fw\r");
JonFreeman 5:21a8ac83142c 439 else
JonFreeman 5:21a8ac83142c 440 com.printf ("re\r");
JonFreeman 5:21a8ac83142c 441 // com.printf ("rvi22 55\rkd\r");
JonFreeman 5:21a8ac83142c 442 throttle (0.0); // Set revs to idle. Start engine and warm up before powering up control
JonFreeman 5:21a8ac83142c 443 setup_pccom ();
JonFreeman 5:21a8ac83142c 444 setup_lococom ();
JonFreeman 5:21a8ac83142c 445 pc.printf ("Jon's Touch Screen Loco 2018 sytem starting up %s\r\n", slider.direction ? "Forward":"Reverse");
JonFreeman 4:67478861c670 446 uint8_t lcd_status = touch_screen.Init(lcd.GetXSize(), lcd.GetYSize());
JonFreeman 4:67478861c670 447 if (lcd_status != TS_OK) {
JonFreeman 4:67478861c670 448 lcd.Clear(LCD_COLOR_RED);
JonFreeman 4:67478861c670 449 lcd.SetBackColor(LCD_COLOR_RED);
JonFreeman 4:67478861c670 450 lcd.SetTextColor(LCD_COLOR_WHITE);
JonFreeman 4:67478861c670 451 lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE);
JonFreeman 4:67478861c670 452 wait (20);
JonFreeman 4:67478861c670 453 } else {
JonFreeman 4:67478861c670 454 lcd.Clear(LCD_COLOR_DARKBLUE);
JonFreeman 4:67478861c670 455 lcd.SetBackColor(LCD_COLOR_GREEN);
JonFreeman 4:67478861c670 456 lcd.SetTextColor(LCD_COLOR_WHITE);
JonFreeman 4:67478861c670 457 lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT OK", CENTER_MODE);
JonFreeman 4:67478861c670 458 }
JonFreeman 4:67478861c670 459
JonFreeman 4:67478861c670 460 lcd.SetFont(&Font16);
JonFreeman 4:67478861c670 461 lcd.Clear(LCD_COLOR_LIGHTGRAY);
JonFreeman 4:67478861c670 462 setup_buttons(); // draws buttons
JonFreeman 4:67478861c670 463
JonFreeman 4:67478861c670 464 slider.oldpos = 0;
JonFreeman 4:67478861c670 465 slider.loco_speed = 0.0;
JonFreeman 4:67478861c670 466 slider.handbrake_effort = 0.1;
JonFreeman 4:67478861c670 467 slider.position = MAX_POS - 2; // Low down in REGEN_BRAKE position - NOT to power-up in PARK
JonFreeman 4:67478861c670 468 SliderGraphic (slider); // sets slider.state to value determined by slider.position
JonFreeman 4:67478861c670 469 set_run_mode (REGEN_BRAKE); // sets slider.mode
JonFreeman 4:67478861c670 470
JonFreeman 4:67478861c670 471 lcd.SetBackColor(LCD_COLOR_DARKBLUE);
JonFreeman 4:67478861c670 472
JonFreeman 4:67478861c670 473 vm_set(); // Draw 3 analogue meter movements, speedo, voltmeter, ammeter
JonFreeman 4:67478861c670 474
JonFreeman 4:67478861c670 475 // odometer_zero ();
JonFreeman 4:67478861c670 476 // pc.printf ("Back from odometer_zero\r\n");
JonFreeman 4:67478861c670 477 double torque_req = 0.0;
JonFreeman 4:67478861c670 478 bool toggle32ms = false;
JonFreeman 4:67478861c670 479 // Main loop
JonFreeman 5:21a8ac83142c 480
JonFreeman 5:21a8ac83142c 481 int boards_fitted[8], bfptr = 0;
JonFreeman 5:21a8ac83142c 482 for (int i = 0; i < 8; i++)
JonFreeman 5:21a8ac83142c 483 boards_fitted[i] = 0;
JonFreeman 5:21a8ac83142c 484 sys_timer_32Hz = 0;
JonFreeman 5:21a8ac83142c 485
JonFreeman 5:21a8ac83142c 486 int last_digit = 0, board_cnt = 0, ch;
JonFreeman 5:21a8ac83142c 487 while (sys_timer_32Hz < 12) { // Sniff out system, discover motor controllers connected
JonFreeman 5:21a8ac83142c 488 while (!trigger_32ms)
JonFreeman 5:21a8ac83142c 489 // command_line_interpreter ();
JonFreeman 5:21a8ac83142c 490 clicore (pccom);
JonFreeman 5:21a8ac83142c 491 trigger_32ms = false;
JonFreeman 5:21a8ac83142c 492 if (sys_timer_32Hz < 11) { // issue "0who\r", "1who\r" ... "9who\r"
JonFreeman 5:21a8ac83142c 493 com.putc ((sys_timer_32Hz - 1) | '0');
JonFreeman 5:21a8ac83142c 494 com.printf ("who\r");
JonFreeman 5:21a8ac83142c 495 }
JonFreeman 5:21a8ac83142c 496 while (com.readable()) {
JonFreeman 5:21a8ac83142c 497 ch = com.getc();
JonFreeman 5:21a8ac83142c 498 if (ch != '\r') {
JonFreeman 5:21a8ac83142c 499 if (isdigit(ch))
JonFreeman 5:21a8ac83142c 500 last_digit = ch;
JonFreeman 5:21a8ac83142c 501 }
JonFreeman 5:21a8ac83142c 502 else { // got '\r' at end of line
JonFreeman 5:21a8ac83142c 503 if (isdigit(last_digit))
JonFreeman 5:21a8ac83142c 504 boards_fitted[board_cnt++] = last_digit;
JonFreeman 5:21a8ac83142c 505 last_digit = 0;
JonFreeman 5:21a8ac83142c 506 }
JonFreeman 5:21a8ac83142c 507 }
JonFreeman 5:21a8ac83142c 508 }
JonFreeman 5:21a8ac83142c 509 while (boards_fitted[bfptr]) { // This works, identified BLDC Motor Controller board ID chars '0' to '9' listed in boards_fitted[]
JonFreeman 5:21a8ac83142c 510 pc.printf ("Board %c found\r\n", boards_fitted[bfptr++]);
JonFreeman 5:21a8ac83142c 511 }
JonFreeman 5:21a8ac83142c 512 clicore (pccom);
JonFreeman 5:21a8ac83142c 513 pc.printf ("pcmenuitems %d, commenuitems %d\r\n", pccom.numof_menu_items, lococom.numof_menu_items);
JonFreeman 5:21a8ac83142c 514 // Done setup, time to roll !
JonFreeman 4:67478861c670 515
JonFreeman 4:67478861c670 516 while (1) {
JonFreeman 4:67478861c670 517
JonFreeman 4:67478861c670 518 struct ky_bd * present_kybd, * previous_kybd;
JonFreeman 4:67478861c670 519 bool sliderpress = false;
JonFreeman 5:21a8ac83142c 520 // command_line_interpreter () ; // Do any actions from command line via usb link
JonFreeman 5:21a8ac83142c 521 clicore (pccom);
JonFreeman 5:21a8ac83142c 522
JonFreeman 4:67478861c670 523 stuff_to_do_every_250us () ;
JonFreeman 4:67478861c670 524
JonFreeman 4:67478861c670 525 if (trigger_32ms == true) { // Stuff to do every 32 milli secs
JonFreeman 4:67478861c670 526 trigger_32ms = false;
JonFreeman 5:21a8ac83142c 527 clicore (lococom);
JonFreeman 4:67478861c670 528 toggle32ms = !toggle32ms;
JonFreeman 4:67478861c670 529 if (toggle32ms) {
JonFreeman 4:67478861c670 530 present_kybd = &kybd_a;
JonFreeman 4:67478861c670 531 previous_kybd = &kybd_b;
JonFreeman 4:67478861c670 532 } else {
JonFreeman 4:67478861c670 533 present_kybd = &kybd_b;
JonFreeman 4:67478861c670 534 previous_kybd = &kybd_a;
JonFreeman 4:67478861c670 535 }
JonFreeman 4:67478861c670 536 read_keypresses (*present_kybd);
JonFreeman 4:67478861c670 537 sliderpress = false;
JonFreeman 4:67478861c670 538 slider.recalc_run = false;
JonFreeman 4:67478861c670 539 int j = 0;
JonFreeman 4:67478861c670 540 // if (present2->count > previous_kybd->count) pc.printf ("More presses\r\n");
JonFreeman 4:67478861c670 541 // if (present2->count < previous_kybd->count) pc.printf ("Fewer presses\r\n");
JonFreeman 4:67478861c670 542 if (present_kybd->count || previous_kybd->count) { // at least one key pressed this time or last time
JonFreeman 4:67478861c670 543 int k;
JonFreeman 4:67478861c670 544 double dbl;
JonFreeman 4:67478861c670 545 // pc.printf ("Keys action may be required");
JonFreeman 4:67478861c670 546 // if key in present and ! in previous, found new key press to handle
JonFreeman 4:67478861c670 547 // if key ! in present and in previous, found new key release to handle
JonFreeman 4:67478861c670 548 if (inlist(*present_kybd, SLIDER)) { // Finger is on slider, so Update slider graphic here
JonFreeman 4:67478861c670 549 sliderpress = true;
JonFreeman 4:67478861c670 550 k = present_kybd->slider_y; // get position of finger on slider
JonFreeman 4:67478861c670 551 if (slider.state == RUN && k != slider.position) // Finger has moved within RUN range
JonFreeman 4:67478861c670 552 slider.recalc_run = true;
JonFreeman 5:21a8ac83142c 553 if (slider.state == RUN && k >= NEUTRAL_VAL) { // Finger has moved from RUN to BRAKE range
JonFreeman 4:67478861c670 554 slider.position = k = NEUTRAL_VAL; // kill drive for rapid reaction to braking
JonFreeman 5:21a8ac83142c 555 throttle (0.0);
JonFreeman 5:21a8ac83142c 556 }
JonFreeman 4:67478861c670 557
JonFreeman 4:67478861c670 558 else { // nice slow non-jerky glidey movement required
JonFreeman 4:67478861c670 559 dbl = (double)(k - slider.position);
JonFreeman 4:67478861c670 560 dbl /= 13.179; // Where did 13.179 come from ?
JonFreeman 4:67478861c670 561 if (dbl < 0.0)
JonFreeman 4:67478861c670 562 dbl -= 1.0;
JonFreeman 4:67478861c670 563 if (dbl > 0.0)
JonFreeman 4:67478861c670 564 dbl += 1.0;
JonFreeman 4:67478861c670 565 slider.position += (int)dbl;
JonFreeman 4:67478861c670 566 }
JonFreeman 4:67478861c670 567 SliderGraphic (slider); // sets slider.state to value determined by slider.position
JonFreeman 4:67478861c670 568 set_run_mode (slider.state);
JonFreeman 4:67478861c670 569 draw_button_hilight (SLIDER, LCD_COLOR_YELLOW) ;
JonFreeman 4:67478861c670 570
JonFreeman 4:67478861c670 571 if (slider.state == REGEN_BRAKE) {
JonFreeman 4:67478861c670 572 double brake_effort = ((double)(slider.position - NEUTRAL_VAL)
JonFreeman 4:67478861c670 573 / (double)(MAX_POS - NEUTRAL_VAL));
JonFreeman 4:67478861c670 574 // brake_effort normalised to range 0.0 to 1.0
JonFreeman 4:67478861c670 575 brake_effort *= 0.97; // upper limit to braking effort, observed effect before was quite fierce
JonFreeman 4:67478861c670 576 pc.printf ("Brake effort %.2f\r\n", brake_effort);
JonFreeman 4:67478861c670 577 /* set_pwm (brake_effort); */
JonFreeman 4:67478861c670 578 set_V_limit (sqrt(brake_effort)); // sqrt gives more linear feel to control
JonFreeman 4:67478861c670 579 set_I_limit (1.0);
JonFreeman 5:21a8ac83142c 580 throttle (0.0);
JonFreeman 4:67478861c670 581 }
JonFreeman 4:67478861c670 582 } else { // pc.printf ("Slider not touched\r\n");
JonFreeman 4:67478861c670 583 }
JonFreeman 4:67478861c670 584
JonFreeman 4:67478861c670 585 j = 0;
JonFreeman 4:67478861c670 586 while (j < present_kybd->count) { // handle new key presses
JonFreeman 4:67478861c670 587 k = present_kybd->ky[j++].keynum;
JonFreeman 4:67478861c670 588 if (inlist(*present_kybd, k)) {
JonFreeman 4:67478861c670 589 switch (k) { // Here for auto-repeat type key behaviour
JonFreeman 4:67478861c670 590 case 21: // key is 'voltmeter'
JonFreeman 5:21a8ac83142c 591 // set_V_limit (last_V * 1.002 + 0.001);
JonFreeman 4:67478861c670 592 break;
JonFreeman 4:67478861c670 593 case 22: // key is 'ammeter'
JonFreeman 5:21a8ac83142c 594 // set_V_limit (last_V * 0.99);
JonFreeman 4:67478861c670 595 break;
JonFreeman 4:67478861c670 596 } // endof switch (k)
JonFreeman 4:67478861c670 597 } // endof if (inlist(*present2, k)) {
JonFreeman 4:67478861c670 598 if (inlist(*present_kybd, k) && !inlist(*previous_kybd, k)) {
JonFreeman 4:67478861c670 599 pc.printf ("Handle Press %d\r\n", k);
JonFreeman 4:67478861c670 600 draw_button_hilight (k, LCD_COLOR_YELLOW) ;
JonFreeman 4:67478861c670 601 switch (k) { // Handle new touch screen button presses here - single action per press, not autorepeat
JonFreeman 4:67478861c670 602 case SPEEDO_BUT: //
JonFreeman 4:67478861c670 603 pc.printf ("Speedometer key pressed %d\r\n", k);
JonFreeman 4:67478861c670 604 break;
JonFreeman 4:67478861c670 605 case VMETER_BUT: //
JonFreeman 4:67478861c670 606 pc.printf ("Voltmeter key pressed %d\r\n", k);
JonFreeman 4:67478861c670 607 break;
JonFreeman 4:67478861c670 608 case AMETER_BUT: //
JonFreeman 4:67478861c670 609 pc.printf ("Ammeter key pressed %d\r\n", k);
JonFreeman 4:67478861c670 610 break;
JonFreeman 4:67478861c670 611 default:
JonFreeman 4:67478861c670 612 pc.printf ("Unhandled keypress %d\r\n", k);
JonFreeman 4:67478861c670 613 break;
JonFreeman 4:67478861c670 614 } // endof switch (button)
JonFreeman 4:67478861c670 615 }
JonFreeman 4:67478861c670 616 } // endof while - handle new key presses
JonFreeman 4:67478861c670 617 j = 0;
JonFreeman 4:67478861c670 618 while (j < previous_kybd->count) { // handle new key releases
JonFreeman 4:67478861c670 619 k = previous_kybd->ky[j++].keynum;
JonFreeman 4:67478861c670 620 if (inlist(*previous_kybd, k) && !inlist(*present_kybd, k)) {
JonFreeman 4:67478861c670 621 pc.printf ("Handle Release %d\r\n", k);
JonFreeman 4:67478861c670 622 draw_button_hilight (k, LCD_COLOR_DARKBLUE) ;
JonFreeman 4:67478861c670 623 }
JonFreeman 4:67478861c670 624 } // endof while - handle new key releases
JonFreeman 4:67478861c670 625 } // endof at least one key pressed this time or last time
JonFreeman 4:67478861c670 626
JonFreeman 4:67478861c670 627 if (sliderpress == false) { // need to glide dead-mans function towards neutral here
JonFreeman 4:67478861c670 628 if (slider.position < NEUTRAL_VAL) {
JonFreeman 4:67478861c670 629 slider.position += 1 + (NEUTRAL_VAL - slider.position) / DAMPER_DECAY;
JonFreeman 4:67478861c670 630 SliderGraphic (slider);
JonFreeman 4:67478861c670 631 slider.recalc_run = true;
JonFreeman 4:67478861c670 632 }
JonFreeman 4:67478861c670 633 }
JonFreeman 4:67478861c670 634
JonFreeman 4:67478861c670 635 if (slider.recalc_run) { // range of slider.position in RUN mode is min_pos_() to NEUTRAL_VAL - 1
JonFreeman 4:67478861c670 636 slider.recalc_run = false; // All RUN power and pwm calcs done here
JonFreeman 4:67478861c670 637 int b = slider.position;
JonFreeman 4:67478861c670 638 // double torque_req; // now declared above to be used as parameter for throttle
JonFreeman 4:67478861c670 639 if (b > NEUTRAL_VAL)
JonFreeman 4:67478861c670 640 b = NEUTRAL_VAL;
JonFreeman 4:67478861c670 641 if (b < MIN_POS) // if finger position is above top of slider limit
JonFreeman 4:67478861c670 642 b = MIN_POS;
JonFreeman 4:67478861c670 643 b = NEUTRAL_VAL - b; // now got integer going positive for increasing power demand
JonFreeman 4:67478861c670 644 torque_req = (double) b;
JonFreeman 4:67478861c670 645 torque_req /= (NEUTRAL_VAL - MIN_POS); // in range 0.0 to 1.0
JonFreeman 5:21a8ac83142c 646 pc.printf ("torque_rec = %.3f, last_V = %.3f\r\n", torque_req, last_V);
JonFreeman 4:67478861c670 647 set_I_limit (torque_req);
JonFreeman 5:21a8ac83142c 648
JonFreeman 5:21a8ac83142c 649 throttle (torque_req); // Think about moderating this and including speed related element
JonFreeman 5:21a8ac83142c 650
JonFreeman 4:67478861c670 651 if (torque_req < 0.05)
JonFreeman 5:21a8ac83142c 652 set_V_limit (last_V / 2.0);
JonFreeman 4:67478861c670 653 else {
JonFreeman 5:21a8ac83142c 654 if (last_V < 0.99)
JonFreeman 5:21a8ac83142c 655 set_V_limit (last_V + 0.05); // ramp voltage up rather than slam to max
JonFreeman 4:67478861c670 656 }
JonFreeman 4:67478861c670 657 }
JonFreeman 4:67478861c670 658 } // endof doing 32ms stuff
JonFreeman 4:67478861c670 659
JonFreeman 4:67478861c670 660 if (qtrsec_trig == true) { // do every quarter second stuff here
JonFreeman 4:67478861c670 661 qtrsec_trig = false;
JonFreeman 5:21a8ac83142c 662 // speed.qtr_sec_update ();
JonFreeman 5:21a8ac83142c 663 // double speedmph = speed.MPH(), amps = 0.0 - read_ammeter(), volts = read_voltmeter();
JonFreeman 5:21a8ac83142c 664 double speedmph = speed2.mph(), amps = 0.0 - read_ammeter(), volts = read_voltmeter();
JonFreeman 4:67478861c670 665 //static const double mph_2_mm_per_sec = 447.04; // exact
JonFreeman 4:67478861c670 666 // double mm_travelled_in_qtrsec = speedmph * mph_2_mm_per_sec / 4.0;
JonFreeman 5:21a8ac83142c 667 // 1.0 mph = 0.44704 metre per sec
JonFreeman 5:21a8ac83142c 668 // = 0.11176 metre per quarter sec
JonFreeman 5:21a8ac83142c 669
JonFreeman 5:21a8ac83142c 670 recent_distance += (speedmph * 111.76); // Convert mph to distance mm travelled in quarter second
JonFreeman 5:21a8ac83142c 671
JonFreeman 4:67478861c670 672 slider.loco_speed = speedmph;
JonFreeman 4:67478861c670 673 electrical_power_Watt = volts * amps; // visible throughout main
JonFreeman 4:67478861c670 674 update_meters (speedmph, electrical_power_Watt, volts) ; // displays speed, volts and power (volts times amps)
JonFreeman 4:67478861c670 675 led_grn = !led_grn;
JonFreeman 4:67478861c670 676 if (slider.state == PARK) {
JonFreeman 4:67478861c670 677 if (speedmph > LOCO_HANDBRAKE_ESCAPE_SPEED / 4.0) {
JonFreeman 4:67478861c670 678 slider.handbrake_effort *= 1.1;
JonFreeman 4:67478861c670 679 if (slider.handbrake_effort > 0.55) slider.handbrake_effort = 0.55;
JonFreeman 4:67478861c670 680 set_run_mode (PARK);
JonFreeman 4:67478861c670 681 pc.printf ("Handbrake slipping, effort %.2f\r\n", slider.handbrake_effort);
JonFreeman 4:67478861c670 682 }
JonFreeman 4:67478861c670 683 if (speedmph < 0.02) {
JonFreeman 4:67478861c670 684 slider.handbrake_effort *= 0.9;
JonFreeman 4:67478861c670 685 if (slider.handbrake_effort < 0.05) slider.handbrake_effort = 0.05;
JonFreeman 4:67478861c670 686 set_run_mode (PARK);
JonFreeman 4:67478861c670 687 pc.printf ("Handbrake not slipping, effort %.2f\r\n", slider.handbrake_effort);
JonFreeman 4:67478861c670 688 }
JonFreeman 4:67478861c670 689 }
JonFreeman 5:21a8ac83142c 690 switch (qtr_sec) { // Can do sequential stuff quarter second apart here
JonFreeman 5:21a8ac83142c 691 case 0:
JonFreeman 5:21a8ac83142c 692 case 2:
JonFreeman 5:21a8ac83142c 693 com.putc (boards_fitted[0]);
JonFreeman 5:21a8ac83142c 694 com.printf ("rpm\r");
JonFreeman 5:21a8ac83142c 695 break;
JonFreeman 5:21a8ac83142c 696 case 1:
JonFreeman 5:21a8ac83142c 697 case 3:
JonFreeman 5:21a8ac83142c 698 com.putc (boards_fitted[1]);
JonFreeman 5:21a8ac83142c 699 com.printf ("rpm\r");
JonFreeman 5:21a8ac83142c 700 break;
JonFreeman 5:21a8ac83142c 701 default:
JonFreeman 5:21a8ac83142c 702 qtr_sec = 0;
JonFreeman 5:21a8ac83142c 703 break;
JonFreeman 5:21a8ac83142c 704 } // End of switch qtr_sec
JonFreeman 4:67478861c670 705 qtr_sec++;
JonFreeman 4:67478861c670 706 // Can do stuff once per second here
JonFreeman 4:67478861c670 707 if(qtr_sec > 3) {
JonFreeman 4:67478861c670 708 qtr_sec = 0;
JonFreeman 4:67478861c670 709 seconds++;
JonFreeman 5:21a8ac83142c 710 com.printf ("kd\r"); // Kick the WatchDog timers in the Twin BLDC drive boards
JonFreeman 4:67478861c670 711 if (seconds > 59) {
JonFreeman 4:67478861c670 712 seconds = 0;
JonFreeman 4:67478861c670 713 minutes++;
JonFreeman 4:67478861c670 714 // do once per minute stuff here
JonFreeman 4:67478861c670 715 } // fall back into once per second
JonFreeman 4:67478861c670 716 #ifdef QSPI
JonFreeman 5:21a8ac83142c 717 /*
JonFreeman 5:21a8ac83142c 718 Odometer Update stuff now needs fixing to take updagte in form of mm travelled in previous period
JonFreeman 5:21a8ac83142c 719
JonFreeman 4:67478861c670 720 //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 721 if (!odometer_update (historic_distance, (uint16_t)electrical_power_Watt, (uint16_t)(volts * 500.0)))
JonFreeman 4:67478861c670 722 pc.printf ("Probs with odometer_update");
JonFreeman 4:67478861c670 723 char dist[20];
JonFreeman 5:21a8ac83142c 724 // sprintf (dist, "%05d m", speed.metres_travelled());
JonFreeman 4:67478861c670 725 displaytext (236, 226, 2, dist);
JonFreeman 5:21a8ac83142c 726 */
JonFreeman 4:67478861c670 727 #endif
JonFreeman 4:67478861c670 728 // calc_motor_amps( mva);
JonFreeman 4:67478861c670 729 } // endof if(qtr_sec > 3
JonFreeman 4:67478861c670 730 } // endof if (qtrsec_trig == true) {
JonFreeman 4:67478861c670 731 } // endof while(1) main programme loop
JonFreeman 4:67478861c670 732 }
JonFreeman 4:67478861c670 733
JonFreeman 4:67478861c670 734
JonFreeman 4:67478861c670 735