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 17:09:18 2018 +0000
Revision:
8:5945d506a872
Parent:
7:3b1f44cd4735
Child:
9:644867052318
Removed custom sin and cos code, this was originally here because library sin and cos caused display breakup, now cured it seems

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 8:5945d506a872 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 int qtr_sec = 0, seconds = 0, minutes = 0;
JonFreeman 7:3b1f44cd4735 343 double electrical_power_Watt = 0.0;
JonFreeman 7:3b1f44cd4735 344 ky_bd kybd_a, kybd_b;
JonFreeman 7:3b1f44cd4735 345 memset (&kybd_a, 0, sizeof(kybd_a));
JonFreeman 7:3b1f44cd4735 346 memset (&kybd_b, 0, sizeof(kybd_b));
JonFreeman 7:3b1f44cd4735 347 pc.baud (9600);
JonFreeman 7:3b1f44cd4735 348 com.baud (19200);
JonFreeman 8:5945d506a872 349 pc.printf ("\r\n\n\nLoco_TS_2018 Loco Controller starting, testing qspi mem\r\n");
JonFreeman 7:3b1f44cd4735 350 // ir.baud (1200);
JonFreeman 7:3b1f44cd4735 351
JonFreeman 7:3b1f44cd4735 352 I_sink1 = 0; // turn outputs off
JonFreeman 7:3b1f44cd4735 353 I_sink2 = 0; // lamp right
JonFreeman 7:3b1f44cd4735 354 I_sink3 = 0; // lamp left
JonFreeman 7:3b1f44cd4735 355 I_sink4 = 0;
JonFreeman 7:3b1f44cd4735 356 I_sink5 = 0;
JonFreeman 7:3b1f44cd4735 357 // spareio_d8.mode (PullUp); now output driving throttle servo
JonFreeman 7:3b1f44cd4735 358 // spareio_d9.mode (PullUp);
JonFreeman 7:3b1f44cd4735 359 spareio_d10.mode(PullUp);
JonFreeman 7:3b1f44cd4735 360
JonFreeman 7:3b1f44cd4735 361 Ticker tick250us;
JonFreeman 7:3b1f44cd4735 362
JonFreeman 7:3b1f44cd4735 363 // Setup User Interrupt Vectors
JonFreeman 7:3b1f44cd4735 364 tick250us.attach_us (&ISR_current_reader, 250); // count 125 of these to trig 31.25ms
JonFreeman 7:3b1f44cd4735 365 // tick32ms.attach_us (&ISR_tick_32ms, 32001);
JonFreeman 7:3b1f44cd4735 366 // tick32ms.attach_us (&ISR_tick_32ms, 31250); // then count 8 pulses per 250ms
JonFreeman 7:3b1f44cd4735 367 // tick250ms.attach_us (&ISR_tick_250ms, 250002);
JonFreeman 4:67478861c670 368 #ifdef QSPI
JonFreeman 4:67478861c670 369
JonFreeman 4:67478861c670 370 extern int qspifindfree (uint8_t* dest, uint32_t addr) ;
JonFreeman 4:67478861c670 371 extern int ask_QSPI_OK () ;
JonFreeman 4:67478861c670 372 extern bool qspimemcheck () ;
JonFreeman 4:67478861c670 373 extern int qspiinit () ;
JonFreeman 4:67478861c670 374 int qspi_ok = ask_QSPI_OK ();
JonFreeman 4:67478861c670 375 //extern int qspieraseblock (uint32_t addr) ;
JonFreeman 4:67478861c670 376 //extern int qspiwr (uint8_t* src, uint32_t addr) ;
JonFreeman 4:67478861c670 377 //extern int qspiwr (uint8_t* src, uint32_t addr, uint32_t len) ;
JonFreeman 4:67478861c670 378 //extern int qspird (uint8_t* dest, uint32_t addr, uint32_t len) ;
JonFreeman 4:67478861c670 379
JonFreeman 4:67478861c670 380 //#define BUFFER_SIZE ((uint32_t)32)
JonFreeman 4:67478861c670 381 //#define QSPI_BUFFER_SIZE ((uint32_t)4270) // Big enough for 4096 byte block
JonFreeman 4:67478861c670 382 //#define WRITE_READ_ADDR ((uint32_t)0x0050)
JonFreeman 4:67478861c670 383 //#define WRITE_READ_ADDR ((uint32_t)0x0010)
JonFreeman 4:67478861c670 384 //#define WRITE_READ_ADDR2 ((uint32_t)0x0020)
JonFreeman 4:67478861c670 385 //#define WRITE_READ_ADDR3 ((uint32_t)0x4030)
JonFreeman 4:67478861c670 386 //#define QSPI_BASE_ADDR ((uint32_t)0x90000000)
JonFreeman 4:67478861c670 387
JonFreeman 4:67478861c670 388 // 123456789012345
JonFreeman 4:67478861c670 389 // uint8_t WriteBuffer[QSPI_BUFFER_SIZE] = "Hello World !!!\0";
JonFreeman 4:67478861c670 390 // uint8_t ReadBuffer[QSPI_BUFFER_SIZE];
JonFreeman 4:67478861c670 391 // const uint8_t MemInitString[] = "Electric Locomotive Controller - Jon Freeman B. Eng. Hons - November 2017\0";
JonFreeman 4:67478861c670 392 // const uint8_t Ifound_String[] = "I found the man sir, god I wish I hadn't!\0";
JonFreeman 4:67478861c670 393
JonFreeman 4:67478861c670 394 // pc.printf ("[%s]\r\n", MemInitString);
JonFreeman 4:67478861c670 395 // pc.printf ("[%s]\r\n", Ifound_String);
JonFreeman 4:67478861c670 396 // pc.printf("\n\nQSPI demo started\r\n");
JonFreeman 4:67478861c670 397
JonFreeman 4:67478861c670 398 // Check initialization
JonFreeman 4:67478861c670 399 if (qspiinit() != qspi_ok)
JonFreeman 4:67478861c670 400 error("Initialization FAILED\r\n");
JonFreeman 4:67478861c670 401 else
JonFreeman 4:67478861c670 402 pc.printf("Initialization PASSED\r\n");
JonFreeman 4:67478861c670 403
JonFreeman 4:67478861c670 404 // Check memory informations
JonFreeman 4:67478861c670 405 if (!qspimemcheck ())
JonFreeman 4:67478861c670 406 pc.printf ("Problem with qspimemcheck\r\n");
JonFreeman 4:67478861c670 407 /* // Erase memory
JonFreeman 4:67478861c670 408 qspieraseblock (WRITE_READ_ADDR);
JonFreeman 4:67478861c670 409 qspieraseblock (WRITE_READ_ADDR2);
JonFreeman 4:67478861c670 410 qspieraseblock (WRITE_READ_ADDR3);
JonFreeman 4:67478861c670 411 qspieraseblock (0x02000);
JonFreeman 4:67478861c670 412 // Write memory
JonFreeman 4:67478861c670 413 qspiwr(WriteBuffer, WRITE_READ_ADDR);
JonFreeman 4:67478861c670 414 qspird(ReadBuffer, WRITE_READ_ADDR, 20);
JonFreeman 4:67478861c670 415 qspiwr((uint8_t*)"Oh what a joy it is.", 0x02000);
JonFreeman 4:67478861c670 416 qspird(ReadBuffer, 0x02000, 20);
JonFreeman 4:67478861c670 417 qspieraseblock (0x02000);
JonFreeman 4:67478861c670 418 */ // Read memory
JonFreeman 4:67478861c670 419 // if (qspi.Read(ReadBuffer, WRITE_READ_ADDR, 11) != QSPI_OK)
JonFreeman 4:67478861c670 420 /* qspird(ReadBuffer, WRITE_READ_ADDR, 256);
JonFreeman 4:67478861c670 421 qspird(ReadBuffer, WRITE_READ_ADDR + 1, 256);
JonFreeman 4:67478861c670 422 qspird(ReadBuffer, 0, 256);
JonFreeman 4:67478861c670 423
JonFreeman 4:67478861c670 424 // Jon's play with Write memory
JonFreeman 4:67478861c670 425 qspiwr ((uint8_t*)MemInitString, WRITE_READ_ADDR2);
JonFreeman 4:67478861c670 426 qspiwr ((uint8_t*)Ifound_String, WRITE_READ_ADDR3);
JonFreeman 4:67478861c670 427
JonFreeman 4:67478861c670 428 qspird(ReadBuffer, 0, 256); // shows correct write of "Electric Locomotive Controller" after "Hello World !!!"
JonFreeman 4:67478861c670 429 qspird(ReadBuffer, WRITE_READ_ADDR2, 250);
JonFreeman 4:67478861c670 430
JonFreeman 4:67478861c670 431 qspird(ReadBuffer, WRITE_READ_ADDR3, 250);
JonFreeman 4:67478861c670 432 pc.printf ("\r\r\r\n");
JonFreeman 4:67478861c670 433 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 434 qspird(ReadBuffer, 0, 4096);
JonFreeman 4:67478861c670 435
JonFreeman 4:67478861c670 436 int pos = qspifindfree (ReadBuffer, 0);
JonFreeman 4:67478861c670 437 pc.printf ("qspifindfree reports %d\r\n", pos);
JonFreeman 4:67478861c670 438 */
JonFreeman 4:67478861c670 439 //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 440
JonFreeman 4:67478861c670 441 #endif
JonFreeman 4:67478861c670 442
JonFreeman 7:3b1f44cd4735 443 if (f_r_switch) {
JonFreeman 4:67478861c670 444 slider.direction = FWD; // make decision from key switch position here
JonFreeman 7:3b1f44cd4735 445 com.printf ("fw\r");
JonFreeman 7:3b1f44cd4735 446 }
JonFreeman 7:3b1f44cd4735 447 else {
JonFreeman 4:67478861c670 448 slider.direction = REV; // make decision from key switch position here
JonFreeman 7:3b1f44cd4735 449 com.printf ("re\r");
JonFreeman 7:3b1f44cd4735 450 }
JonFreeman 4:67478861c670 451 // 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 452 // maxv.period_ticks (MAX_PWM_TICKS + 1); // around 18 kHz
JonFreeman 5:21a8ac83142c 453 // maxi.period_ticks (MAX_PWM_TICKS + 1);
JonFreeman 4:67478861c670 454 set_I_limit (0.0);
JonFreeman 4:67478861c670 455 set_V_limit (0.0);
JonFreeman 5:21a8ac83142c 456 throttle (0.0); // Set revs to idle. Start engine and warm up before powering up control
JonFreeman 5:21a8ac83142c 457 setup_pccom ();
JonFreeman 5:21a8ac83142c 458 setup_lococom ();
JonFreeman 5:21a8ac83142c 459 pc.printf ("Jon's Touch Screen Loco 2018 sytem starting up %s\r\n", slider.direction ? "Forward":"Reverse");
JonFreeman 4:67478861c670 460 uint8_t lcd_status = touch_screen.Init(lcd.GetXSize(), lcd.GetYSize());
JonFreeman 4:67478861c670 461 if (lcd_status != TS_OK) {
JonFreeman 4:67478861c670 462 lcd.Clear(LCD_COLOR_RED);
JonFreeman 4:67478861c670 463 lcd.SetBackColor(LCD_COLOR_RED);
JonFreeman 4:67478861c670 464 lcd.SetTextColor(LCD_COLOR_WHITE);
JonFreeman 4:67478861c670 465 lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE);
JonFreeman 4:67478861c670 466 wait (20);
JonFreeman 4:67478861c670 467 } else {
JonFreeman 4:67478861c670 468 lcd.Clear(LCD_COLOR_DARKBLUE);
JonFreeman 4:67478861c670 469 lcd.SetBackColor(LCD_COLOR_GREEN);
JonFreeman 4:67478861c670 470 lcd.SetTextColor(LCD_COLOR_WHITE);
JonFreeman 4:67478861c670 471 lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT OK", CENTER_MODE);
JonFreeman 4:67478861c670 472 }
JonFreeman 4:67478861c670 473
JonFreeman 4:67478861c670 474 lcd.SetFont(&Font16);
JonFreeman 4:67478861c670 475 lcd.Clear(LCD_COLOR_LIGHTGRAY);
JonFreeman 4:67478861c670 476 setup_buttons(); // draws buttons
JonFreeman 4:67478861c670 477
JonFreeman 4:67478861c670 478 slider.oldpos = 0;
JonFreeman 4:67478861c670 479 slider.loco_speed = 0.0;
JonFreeman 4:67478861c670 480 slider.handbrake_effort = 0.1;
JonFreeman 4:67478861c670 481 slider.position = MAX_POS - 2; // Low down in REGEN_BRAKE position - NOT to power-up in PARK
JonFreeman 4:67478861c670 482 SliderGraphic (slider); // sets slider.state to value determined by slider.position
JonFreeman 4:67478861c670 483 set_run_mode (REGEN_BRAKE); // sets slider.mode
JonFreeman 4:67478861c670 484
JonFreeman 4:67478861c670 485 lcd.SetBackColor(LCD_COLOR_DARKBLUE);
JonFreeman 4:67478861c670 486
JonFreeman 4:67478861c670 487 vm_set(); // Draw 3 analogue meter movements, speedo, voltmeter, ammeter
JonFreeman 4:67478861c670 488
JonFreeman 7:3b1f44cd4735 489 // if (odometer_zero ())
JonFreeman 7:3b1f44cd4735 490 // pc.printf ("TRUE from odometer_zero\r\n");
JonFreeman 7:3b1f44cd4735 491 // else
JonFreeman 7:3b1f44cd4735 492 // pc.printf ("FALSE from odometer_zero\r\n");
JonFreeman 4:67478861c670 493 double torque_req = 0.0;
JonFreeman 4:67478861c670 494 bool toggle32ms = false;
JonFreeman 4:67478861c670 495 // Main loop
JonFreeman 5:21a8ac83142c 496
JonFreeman 7:3b1f44cd4735 497 uint32_t boards_fitted[8], bfptr = 0;
JonFreeman 5:21a8ac83142c 498 for (int i = 0; i < 8; i++)
JonFreeman 5:21a8ac83142c 499 boards_fitted[i] = 0;
JonFreeman 5:21a8ac83142c 500 sys_timer_32Hz = 0;
JonFreeman 5:21a8ac83142c 501
JonFreeman 5:21a8ac83142c 502 int last_digit = 0, board_cnt = 0, ch;
JonFreeman 5:21a8ac83142c 503 while (sys_timer_32Hz < 12) { // Sniff out system, discover motor controllers connected
JonFreeman 5:21a8ac83142c 504 while (!trigger_32ms)
JonFreeman 5:21a8ac83142c 505 // command_line_interpreter ();
JonFreeman 5:21a8ac83142c 506 clicore (pccom);
JonFreeman 5:21a8ac83142c 507 trigger_32ms = false;
JonFreeman 5:21a8ac83142c 508 if (sys_timer_32Hz < 11) { // issue "0who\r", "1who\r" ... "9who\r"
JonFreeman 5:21a8ac83142c 509 com.putc ((sys_timer_32Hz - 1) | '0');
JonFreeman 5:21a8ac83142c 510 com.printf ("who\r");
JonFreeman 5:21a8ac83142c 511 }
JonFreeman 5:21a8ac83142c 512 while (com.readable()) {
JonFreeman 5:21a8ac83142c 513 ch = com.getc();
JonFreeman 5:21a8ac83142c 514 if (ch != '\r') {
JonFreeman 5:21a8ac83142c 515 if (isdigit(ch))
JonFreeman 5:21a8ac83142c 516 last_digit = ch;
JonFreeman 5:21a8ac83142c 517 }
JonFreeman 5:21a8ac83142c 518 else { // got '\r' at end of line
JonFreeman 5:21a8ac83142c 519 if (isdigit(last_digit))
JonFreeman 5:21a8ac83142c 520 boards_fitted[board_cnt++] = last_digit;
JonFreeman 5:21a8ac83142c 521 last_digit = 0;
JonFreeman 5:21a8ac83142c 522 }
JonFreeman 5:21a8ac83142c 523 }
JonFreeman 5:21a8ac83142c 524 }
JonFreeman 7:3b1f44cd4735 525
JonFreeman 7:3b1f44cd4735 526 // boards_fitted[0] = '4';
JonFreeman 7:3b1f44cd4735 527 // boards_fitted[1] = '5';
JonFreeman 7:3b1f44cd4735 528
JonFreeman 5:21a8ac83142c 529 while (boards_fitted[bfptr]) { // This works, identified BLDC Motor Controller board ID chars '0' to '9' listed in boards_fitted[]
JonFreeman 5:21a8ac83142c 530 pc.printf ("Board %c found\r\n", boards_fitted[bfptr++]);
JonFreeman 5:21a8ac83142c 531 }
JonFreeman 7:3b1f44cd4735 532 speed.set_board_IDs (boards_fitted); // store number and IDs of Dual BLDC boards identified
JonFreeman 7:3b1f44cd4735 533 bfptr = 0;
JonFreeman 5:21a8ac83142c 534 clicore (pccom);
JonFreeman 5:21a8ac83142c 535 pc.printf ("pcmenuitems %d, commenuitems %d\r\n", pccom.numof_menu_items, lococom.numof_menu_items);
JonFreeman 7:3b1f44cd4735 536 // perror (strerror(errno));
JonFreeman 5:21a8ac83142c 537 // Done setup, time to roll !
JonFreeman 4:67478861c670 538
JonFreeman 7:3b1f44cd4735 539 lights (1); // Headlights ON!
JonFreeman 7:3b1f44cd4735 540
JonFreeman 4:67478861c670 541 while (1) {
JonFreeman 4:67478861c670 542
JonFreeman 4:67478861c670 543 struct ky_bd * present_kybd, * previous_kybd;
JonFreeman 4:67478861c670 544 bool sliderpress = false;
JonFreeman 5:21a8ac83142c 545 // command_line_interpreter () ; // Do any actions from command line via usb link
JonFreeman 5:21a8ac83142c 546 clicore (pccom);
JonFreeman 5:21a8ac83142c 547
JonFreeman 4:67478861c670 548 stuff_to_do_every_250us () ;
JonFreeman 4:67478861c670 549
JonFreeman 4:67478861c670 550 if (trigger_32ms == true) { // Stuff to do every 32 milli secs
JonFreeman 4:67478861c670 551 trigger_32ms = false;
JonFreeman 7:3b1f44cd4735 552 clicore (lococom);
JonFreeman 4:67478861c670 553 toggle32ms = !toggle32ms;
JonFreeman 4:67478861c670 554 if (toggle32ms) {
JonFreeman 4:67478861c670 555 present_kybd = &kybd_a;
JonFreeman 4:67478861c670 556 previous_kybd = &kybd_b;
JonFreeman 4:67478861c670 557 } else {
JonFreeman 4:67478861c670 558 present_kybd = &kybd_b;
JonFreeman 4:67478861c670 559 previous_kybd = &kybd_a;
JonFreeman 4:67478861c670 560 }
JonFreeman 4:67478861c670 561 read_keypresses (*present_kybd);
JonFreeman 4:67478861c670 562 sliderpress = false;
JonFreeman 4:67478861c670 563 slider.recalc_run = false;
JonFreeman 4:67478861c670 564 int j = 0;
JonFreeman 4:67478861c670 565 // if (present2->count > previous_kybd->count) pc.printf ("More presses\r\n");
JonFreeman 4:67478861c670 566 // if (present2->count < previous_kybd->count) pc.printf ("Fewer presses\r\n");
JonFreeman 4:67478861c670 567 if (present_kybd->count || previous_kybd->count) { // at least one key pressed this time or last time
JonFreeman 4:67478861c670 568 int k;
JonFreeman 4:67478861c670 569 double dbl;
JonFreeman 4:67478861c670 570 // pc.printf ("Keys action may be required");
JonFreeman 4:67478861c670 571 // if key in present and ! in previous, found new key press to handle
JonFreeman 4:67478861c670 572 // if key ! in present and in previous, found new key release to handle
JonFreeman 4:67478861c670 573 if (inlist(*present_kybd, SLIDER)) { // Finger is on slider, so Update slider graphic here
JonFreeman 4:67478861c670 574 sliderpress = true;
JonFreeman 4:67478861c670 575 k = present_kybd->slider_y; // get position of finger on slider
JonFreeman 4:67478861c670 576 if (slider.state == RUN && k != slider.position) // Finger has moved within RUN range
JonFreeman 4:67478861c670 577 slider.recalc_run = true;
JonFreeman 5:21a8ac83142c 578 if (slider.state == RUN && k >= NEUTRAL_VAL) { // Finger has moved from RUN to BRAKE range
JonFreeman 4:67478861c670 579 slider.position = k = NEUTRAL_VAL; // kill drive for rapid reaction to braking
JonFreeman 5:21a8ac83142c 580 throttle (0.0);
JonFreeman 5:21a8ac83142c 581 }
JonFreeman 4:67478861c670 582
JonFreeman 4:67478861c670 583 else { // nice slow non-jerky glidey movement required
JonFreeman 4:67478861c670 584 dbl = (double)(k - slider.position);
JonFreeman 4:67478861c670 585 dbl /= 13.179; // Where did 13.179 come from ?
JonFreeman 4:67478861c670 586 if (dbl < 0.0)
JonFreeman 4:67478861c670 587 dbl -= 1.0;
JonFreeman 4:67478861c670 588 if (dbl > 0.0)
JonFreeman 4:67478861c670 589 dbl += 1.0;
JonFreeman 4:67478861c670 590 slider.position += (int)dbl;
JonFreeman 4:67478861c670 591 }
JonFreeman 4:67478861c670 592 SliderGraphic (slider); // sets slider.state to value determined by slider.position
JonFreeman 4:67478861c670 593 set_run_mode (slider.state);
JonFreeman 4:67478861c670 594 draw_button_hilight (SLIDER, LCD_COLOR_YELLOW) ;
JonFreeman 4:67478861c670 595
JonFreeman 4:67478861c670 596 if (slider.state == REGEN_BRAKE) {
JonFreeman 4:67478861c670 597 double brake_effort = ((double)(slider.position - NEUTRAL_VAL)
JonFreeman 4:67478861c670 598 / (double)(MAX_POS - NEUTRAL_VAL));
JonFreeman 4:67478861c670 599 // brake_effort normalised to range 0.0 to 1.0
JonFreeman 4:67478861c670 600 brake_effort *= 0.97; // upper limit to braking effort, observed effect before was quite fierce
JonFreeman 4:67478861c670 601 pc.printf ("Brake effort %.2f\r\n", brake_effort);
JonFreeman 4:67478861c670 602 /* set_pwm (brake_effort); */
JonFreeman 4:67478861c670 603 set_V_limit (sqrt(brake_effort)); // sqrt gives more linear feel to control
JonFreeman 4:67478861c670 604 set_I_limit (1.0);
JonFreeman 5:21a8ac83142c 605 throttle (0.0);
JonFreeman 4:67478861c670 606 }
JonFreeman 4:67478861c670 607 } else { // pc.printf ("Slider not touched\r\n");
JonFreeman 4:67478861c670 608 }
JonFreeman 4:67478861c670 609
JonFreeman 4:67478861c670 610 j = 0;
JonFreeman 4:67478861c670 611 while (j < present_kybd->count) { // handle new key presses
JonFreeman 4:67478861c670 612 k = present_kybd->ky[j++].keynum;
JonFreeman 4:67478861c670 613 if (inlist(*present_kybd, k)) {
JonFreeman 4:67478861c670 614 switch (k) { // Here for auto-repeat type key behaviour
JonFreeman 4:67478861c670 615 case 21: // key is 'voltmeter'
JonFreeman 5:21a8ac83142c 616 // set_V_limit (last_V * 1.002 + 0.001);
JonFreeman 4:67478861c670 617 break;
JonFreeman 4:67478861c670 618 case 22: // key is 'ammeter'
JonFreeman 5:21a8ac83142c 619 // set_V_limit (last_V * 0.99);
JonFreeman 4:67478861c670 620 break;
JonFreeman 4:67478861c670 621 } // endof switch (k)
JonFreeman 4:67478861c670 622 } // endof if (inlist(*present2, k)) {
JonFreeman 7:3b1f44cd4735 623 if (inlist(*present_kybd, k) && !inlist(*previous_kybd, k)) { // New key press detected
JonFreeman 4:67478861c670 624 pc.printf ("Handle Press %d\r\n", k);
JonFreeman 4:67478861c670 625 draw_button_hilight (k, LCD_COLOR_YELLOW) ;
JonFreeman 4:67478861c670 626 switch (k) { // Handle new touch screen button presses here - single action per press, not autorepeat
JonFreeman 4:67478861c670 627 case SPEEDO_BUT: //
JonFreeman 4:67478861c670 628 pc.printf ("Speedometer key pressed %d\r\n", k);
JonFreeman 4:67478861c670 629 break;
JonFreeman 4:67478861c670 630 case VMETER_BUT: //
JonFreeman 7:3b1f44cd4735 631 // pc.printf ("Voltmeter key pressed %d\r\n", k);
JonFreeman 7:3b1f44cd4735 632 I_sink5 = 1; // Turn on hi-horn
JonFreeman 4:67478861c670 633 break;
JonFreeman 4:67478861c670 634 case AMETER_BUT: //
JonFreeman 7:3b1f44cd4735 635 // pc.printf ("Ammeter key pressed %d\r\n", k);
JonFreeman 7:3b1f44cd4735 636 I_sink4 = 1; // Turn on lo-horn
JonFreeman 4:67478861c670 637 break;
JonFreeman 4:67478861c670 638 default:
JonFreeman 4:67478861c670 639 pc.printf ("Unhandled keypress %d\r\n", k);
JonFreeman 4:67478861c670 640 break;
JonFreeman 4:67478861c670 641 } // endof switch (button)
JonFreeman 4:67478861c670 642 }
JonFreeman 4:67478861c670 643 } // endof while - handle new key presses
JonFreeman 4:67478861c670 644 j = 0;
JonFreeman 4:67478861c670 645 while (j < previous_kybd->count) { // handle new key releases
JonFreeman 4:67478861c670 646 k = previous_kybd->ky[j++].keynum;
JonFreeman 4:67478861c670 647 if (inlist(*previous_kybd, k) && !inlist(*present_kybd, k)) {
JonFreeman 4:67478861c670 648 pc.printf ("Handle Release %d\r\n", k);
JonFreeman 4:67478861c670 649 draw_button_hilight (k, LCD_COLOR_DARKBLUE) ;
JonFreeman 7:3b1f44cd4735 650 switch (k) { // Handle new touch screen button RELEASes here - single action per press, not autorepeat
JonFreeman 7:3b1f44cd4735 651 case SPEEDO_BUT: //
JonFreeman 7:3b1f44cd4735 652 pc.printf ("Speedometer key released %d\r\n", k);
JonFreeman 7:3b1f44cd4735 653 break;
JonFreeman 7:3b1f44cd4735 654 case VMETER_BUT: //
JonFreeman 7:3b1f44cd4735 655 I_sink5 = 0; // Turn hi-tone horn off
JonFreeman 7:3b1f44cd4735 656 // pc.printf ("Voltmeter key released %d\r\n", k);
JonFreeman 7:3b1f44cd4735 657 break;
JonFreeman 7:3b1f44cd4735 658 case AMETER_BUT: //
JonFreeman 7:3b1f44cd4735 659 I_sink4 = 0; // Turn lo-tone horn off
JonFreeman 7:3b1f44cd4735 660 // pc.printf ("Ammeter key released %d\r\n", k);
JonFreeman 7:3b1f44cd4735 661 break;
JonFreeman 7:3b1f44cd4735 662 default:
JonFreeman 7:3b1f44cd4735 663 pc.printf ("Unhandled keyreleas %d\r\n", k);
JonFreeman 7:3b1f44cd4735 664 break;
JonFreeman 7:3b1f44cd4735 665 } // endof switch (button)
JonFreeman 4:67478861c670 666 }
JonFreeman 4:67478861c670 667 } // endof while - handle new key releases
JonFreeman 4:67478861c670 668 } // endof at least one key pressed this time or last time
JonFreeman 4:67478861c670 669
JonFreeman 4:67478861c670 670 if (sliderpress == false) { // need to glide dead-mans function towards neutral here
JonFreeman 4:67478861c670 671 if (slider.position < NEUTRAL_VAL) {
JonFreeman 4:67478861c670 672 slider.position += 1 + (NEUTRAL_VAL - slider.position) / DAMPER_DECAY;
JonFreeman 4:67478861c670 673 SliderGraphic (slider);
JonFreeman 4:67478861c670 674 slider.recalc_run = true;
JonFreeman 4:67478861c670 675 }
JonFreeman 4:67478861c670 676 }
JonFreeman 4:67478861c670 677
JonFreeman 4:67478861c670 678 if (slider.recalc_run) { // range of slider.position in RUN mode is min_pos_() to NEUTRAL_VAL - 1
JonFreeman 4:67478861c670 679 slider.recalc_run = false; // All RUN power and pwm calcs done here
JonFreeman 4:67478861c670 680 int b = slider.position;
JonFreeman 4:67478861c670 681 if (b > NEUTRAL_VAL)
JonFreeman 4:67478861c670 682 b = NEUTRAL_VAL;
JonFreeman 4:67478861c670 683 if (b < MIN_POS) // if finger position is above top of slider limit
JonFreeman 4:67478861c670 684 b = MIN_POS;
JonFreeman 4:67478861c670 685 b = NEUTRAL_VAL - b; // now got integer going positive for increasing power demand
JonFreeman 4:67478861c670 686 torque_req = (double) b;
JonFreeman 4:67478861c670 687 torque_req /= (NEUTRAL_VAL - MIN_POS); // in range 0.0 to 1.0
JonFreeman 5:21a8ac83142c 688 pc.printf ("torque_rec = %.3f, last_V = %.3f\r\n", torque_req, last_V);
JonFreeman 4:67478861c670 689 set_I_limit (torque_req);
JonFreeman 7:3b1f44cd4735 690 if (torque_req < 0.05) {
JonFreeman 5:21a8ac83142c 691 set_V_limit (last_V / 2.0);
JonFreeman 7:3b1f44cd4735 692 throttle (torque_req * 6.0);
JonFreeman 7:3b1f44cd4735 693 }
JonFreeman 4:67478861c670 694 else {
JonFreeman 7:3b1f44cd4735 695 throttle (0.3 + (torque_req / 2.0));
JonFreeman 5:21a8ac83142c 696 if (last_V < 0.99)
JonFreeman 5:21a8ac83142c 697 set_V_limit (last_V + 0.05); // ramp voltage up rather than slam to max
JonFreeman 4:67478861c670 698 }
JonFreeman 4:67478861c670 699 }
JonFreeman 4:67478861c670 700 } // endof doing 32ms stuff
JonFreeman 4:67478861c670 701
JonFreeman 4:67478861c670 702 if (qtrsec_trig == true) { // do every quarter second stuff here
JonFreeman 4:67478861c670 703 qtrsec_trig = false;
JonFreeman 7:3b1f44cd4735 704 double speedmph = speed.mph(), amps = read_ammeter(), volts = read_voltmeter();
JonFreeman 4:67478861c670 705 slider.loco_speed = speedmph;
JonFreeman 4:67478861c670 706 electrical_power_Watt = volts * amps; // visible throughout main
JonFreeman 4:67478861c670 707 update_meters (speedmph, electrical_power_Watt, volts) ; // displays speed, volts and power (volts times amps)
JonFreeman 4:67478861c670 708 led_grn = !led_grn;
JonFreeman 4:67478861c670 709 if (slider.state == PARK) {
JonFreeman 4:67478861c670 710 if (speedmph > LOCO_HANDBRAKE_ESCAPE_SPEED / 4.0) {
JonFreeman 4:67478861c670 711 slider.handbrake_effort *= 1.1;
JonFreeman 4:67478861c670 712 if (slider.handbrake_effort > 0.55) slider.handbrake_effort = 0.55;
JonFreeman 4:67478861c670 713 set_run_mode (PARK);
JonFreeman 4:67478861c670 714 pc.printf ("Handbrake slipping, effort %.2f\r\n", slider.handbrake_effort);
JonFreeman 4:67478861c670 715 }
JonFreeman 4:67478861c670 716 if (speedmph < 0.02) {
JonFreeman 4:67478861c670 717 slider.handbrake_effort *= 0.9;
JonFreeman 4:67478861c670 718 if (slider.handbrake_effort < 0.05) slider.handbrake_effort = 0.05;
JonFreeman 4:67478861c670 719 set_run_mode (PARK);
JonFreeman 4:67478861c670 720 pc.printf ("Handbrake not slipping, effort %.2f\r\n", slider.handbrake_effort);
JonFreeman 4:67478861c670 721 }
JonFreeman 4:67478861c670 722 }
JonFreeman 7:3b1f44cd4735 723 speed.request_rpm (); // issues "'n'rpm\r", takes care of cycling through available boards in sequence
JonFreeman 7:3b1f44cd4735 724 // switch (qtr_sec) { // Can do sequential stuff quarter second apart here
JonFreeman 7:3b1f44cd4735 725 // } // End of switch qtr_sec
JonFreeman 4:67478861c670 726 qtr_sec++;
JonFreeman 4:67478861c670 727 // Can do stuff once per second here
JonFreeman 4:67478861c670 728 if(qtr_sec > 3) {
JonFreeman 4:67478861c670 729 qtr_sec = 0;
JonFreeman 4:67478861c670 730 seconds++;
JonFreeman 5:21a8ac83142c 731 com.printf ("kd\r"); // Kick the WatchDog timers in the Twin BLDC drive boards
JonFreeman 4:67478861c670 732 if (seconds > 59) {
JonFreeman 4:67478861c670 733 seconds = 0;
JonFreeman 4:67478861c670 734 minutes++;
JonFreeman 4:67478861c670 735 // do once per minute stuff here
JonFreeman 4:67478861c670 736 } // fall back into once per second
JonFreeman 4:67478861c670 737 #ifdef QSPI
JonFreeman 7:3b1f44cd4735 738
JonFreeman 7:3b1f44cd4735 739 // recent_distance += 300;
JonFreeman 7:3b1f44cd4735 740
JonFreeman 7:3b1f44cd4735 741 recent_distance += (speedmph * (111.76 * 4.0)); // Convert mph to distance mm travelled in one second
JonFreeman 7:3b1f44cd4735 742 uint32_t new_metres = ((uint32_t)recent_distance) / 1000;
JonFreeman 7:3b1f44cd4735 743 recent_distance -= (double)(new_metres * 1000);
JonFreeman 7:3b1f44cd4735 744 if (!odometer_update (new_metres, (uint16_t)electrical_power_Watt, (uint16_t)(volts * 500.0)))
JonFreeman 7:3b1f44cd4735 745 pc.printf ("Probs with odometer_update");
JonFreeman 7:3b1f44cd4735 746 char dist[20];
JonFreeman 7:3b1f44cd4735 747 sprintf (dist, "%05d m", odometer_out());
JonFreeman 7:3b1f44cd4735 748 displaytext (236, 226, 2, dist);
JonFreeman 7:3b1f44cd4735 749
JonFreeman 5:21a8ac83142c 750 /*
JonFreeman 5:21a8ac83142c 751 Odometer Update stuff now needs fixing to take updagte in form of mm travelled in previous period
JonFreeman 5:21a8ac83142c 752
JonFreeman 4:67478861c670 753 //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 754 bool distance_measurement::update (uint32_t new_metres_travelled, uint16_t powr, uint16_t volt) {
JonFreeman 4:67478861c670 755 if (!odometer_update (historic_distance, (uint16_t)electrical_power_Watt, (uint16_t)(volts * 500.0)))
JonFreeman 4:67478861c670 756 pc.printf ("Probs with odometer_update");
JonFreeman 4:67478861c670 757 char dist[20];
JonFreeman 5:21a8ac83142c 758 // sprintf (dist, "%05d m", speed.metres_travelled());
JonFreeman 4:67478861c670 759 displaytext (236, 226, 2, dist);
JonFreeman 5:21a8ac83142c 760 */
JonFreeman 4:67478861c670 761 #endif
JonFreeman 4:67478861c670 762 // calc_motor_amps( mva);
JonFreeman 4:67478861c670 763 } // endof if(qtr_sec > 3
JonFreeman 4:67478861c670 764 } // endof if (qtrsec_trig == true) {
JonFreeman 4:67478861c670 765 } // endof while(1) main programme loop
JonFreeman 4:67478861c670 766 }
JonFreeman 4:67478861c670 767
JonFreeman 4:67478861c670 768
JonFreeman 4:67478861c670 769