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:
Wed May 09 15:42:43 2018 +0000
Revision:
7:3b1f44cd4735
Parent:
5:21a8ac83142c
Child:
8:5945d506a872
Panic recovery from updating mbed lib causing total wipeout

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