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:
Mon Apr 09 07:51:37 2018 +0000
Revision:
4:67478861c670
Parent:
3:33086de19b14
Child:
5:21a8ac83142c
First edit of code from 2017 for new Twin BLDC controller boards

Who changed what in which revision?

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