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 Mar 04 17:47:27 2019 +0000
Revision:
14:6bcec5ac21ca
Parent:
12:a25bdf135348
'Brute' Locomotive Touch Screen Controller - Driver's Controls; Always a 'Work In Progress', snapshot March 2019

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JonFreeman 12:a25bdf135348 1 #include "mbed.h"
JonFreeman 12:a25bdf135348 2 #include "TS_DISCO_F746NG.h"
JonFreeman 12:a25bdf135348 3 #include "LCD_DISCO_F746NG.h"
JonFreeman 12:a25bdf135348 4 #include "Electric_Loco.h"
JonFreeman 12:a25bdf135348 5
JonFreeman 12:a25bdf135348 6 extern LCD_DISCO_F746NG lcd;
JonFreeman 12:a25bdf135348 7 static const int char_widths[] = {5, 7, 11, 14, 17, 17} ,
JonFreeman 12:a25bdf135348 8 meter_radius_min = 30, meter_radius_max = 120;
JonFreeman 12:a25bdf135348 9 extern void displaytext (int x, int y, const int font, char * txt) ;
JonFreeman 12:a25bdf135348 10
JonFreeman 12:a25bdf135348 11 void moving_coil_meter::DrawNeedle (double alpha, int colour)
JonFreeman 12:a25bdf135348 12 {
JonFreeman 12:a25bdf135348 13 uint16_t x1, x2, x3, y1, y2, y3;
JonFreeman 12:a25bdf135348 14 int save_colour, ssa, sca;
JonFreeman 12:a25bdf135348 15 while (alpha > PI) alpha -= TWO_PI;
JonFreeman 12:a25bdf135348 16 while (alpha < 0.0) alpha += TWO_PI;
JonFreeman 12:a25bdf135348 17 double shortln = (needle_len / 18.7),
JonFreeman 12:a25bdf135348 18 sina = sin(alpha),
JonFreeman 12:a25bdf135348 19 cosa = cos(alpha);
JonFreeman 12:a25bdf135348 20
JonFreeman 12:a25bdf135348 21 save_colour = lcd.GetTextColor ();
JonFreeman 12:a25bdf135348 22 ssa = (int)(shortln * sina);
JonFreeman 12:a25bdf135348 23 sca = (int)(shortln * cosa);
JonFreeman 12:a25bdf135348 24 old_angle = alpha;
JonFreeman 12:a25bdf135348 25 x1 = cent_x - ssa;//(int)(shortln * sin(alpha));
JonFreeman 12:a25bdf135348 26 y1 = cent_y - sca;//(int)(shortln * cos(alpha));
JonFreeman 12:a25bdf135348 27 x2 = cent_x + (int)(needle_len * cosa);
JonFreeman 12:a25bdf135348 28 y2 = cent_y - (int)(needle_len * sina); // - as increasing y is downwards
JonFreeman 12:a25bdf135348 29 x3 = cent_x + ssa;//(int)(shortln * sin(alpha));
JonFreeman 12:a25bdf135348 30 y3 = cent_y + sca;//(int)(shortln * cos(alpha));
JonFreeman 12:a25bdf135348 31 lcd.SetTextColor (colour);
JonFreeman 12:a25bdf135348 32 lcd.FillCircle (cent_x, cent_y, (int)(needle_len / 15.0));
JonFreeman 12:a25bdf135348 33 // FillTriangle (x1, x2, x3, y1, y2, y3);
JonFreeman 12:a25bdf135348 34
JonFreeman 12:a25bdf135348 35 //static void FillTriangle(uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3)
JonFreeman 12:a25bdf135348 36 //{
JonFreeman 12:a25bdf135348 37 int16_t deltax = 0, deltay = 0, x, y, xinc1 = 0, xinc2 = 0,
JonFreeman 12:a25bdf135348 38 yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0,
JonFreeman 12:a25bdf135348 39 curpixel = 0;
JonFreeman 12:a25bdf135348 40
JonFreeman 12:a25bdf135348 41 deltax = abs(x2 - x1); /* The difference between the x's */
JonFreeman 12:a25bdf135348 42 deltay = abs(y2 - y1); /* The difference between the y's */
JonFreeman 12:a25bdf135348 43 x = x1; /* Start x off at the first pixel */
JonFreeman 12:a25bdf135348 44 y = y1; /* Start y off at the first pixel */
JonFreeman 12:a25bdf135348 45
JonFreeman 12:a25bdf135348 46 if (x2 >= x1) { /* The x-values are increasing */
JonFreeman 12:a25bdf135348 47 xinc1 = 1;
JonFreeman 12:a25bdf135348 48 xinc2 = 1;
JonFreeman 12:a25bdf135348 49 } else { /* The x-values are decreasing */
JonFreeman 12:a25bdf135348 50 xinc1 = -1;
JonFreeman 12:a25bdf135348 51 xinc2 = -1;
JonFreeman 12:a25bdf135348 52 }
JonFreeman 12:a25bdf135348 53
JonFreeman 12:a25bdf135348 54 if (y2 >= y1) { /* The y-values are increasing */
JonFreeman 12:a25bdf135348 55 yinc1 = 1;
JonFreeman 12:a25bdf135348 56 yinc2 = 1;
JonFreeman 12:a25bdf135348 57 } else { /* The y-values are decreasing */
JonFreeman 12:a25bdf135348 58 yinc1 = -1;
JonFreeman 12:a25bdf135348 59 yinc2 = -1;
JonFreeman 12:a25bdf135348 60 }
JonFreeman 12:a25bdf135348 61
JonFreeman 12:a25bdf135348 62 if (deltax >= deltay) { /* There is at least one x-value for every y-value */
JonFreeman 12:a25bdf135348 63 xinc1 = 0; /* Don't change the x when numerator >= denominator */
JonFreeman 12:a25bdf135348 64 yinc2 = 0; /* Don't change the y for every iteration */
JonFreeman 12:a25bdf135348 65 den = deltax;
JonFreeman 12:a25bdf135348 66 num = deltax / 2;
JonFreeman 12:a25bdf135348 67 num_add = deltay;
JonFreeman 12:a25bdf135348 68 num_pixels = deltax; /* There are more x-values than y-values */
JonFreeman 12:a25bdf135348 69 } else { /* There is at least one y-value for every x-value */
JonFreeman 12:a25bdf135348 70 xinc2 = 0; /* Don't change the x for every iteration */
JonFreeman 12:a25bdf135348 71 yinc1 = 0; /* Don't change the y when numerator >= denominator */
JonFreeman 12:a25bdf135348 72 den = deltay;
JonFreeman 12:a25bdf135348 73 num = deltay / 2;
JonFreeman 12:a25bdf135348 74 num_add = deltax;
JonFreeman 12:a25bdf135348 75 num_pixels = deltay; /* There are more y-values than x-values */
JonFreeman 12:a25bdf135348 76 }
JonFreeman 12:a25bdf135348 77
JonFreeman 12:a25bdf135348 78 for (curpixel = 0; curpixel <= num_pixels; curpixel++) {
JonFreeman 12:a25bdf135348 79 lcd.DrawLine(x, y, x3, y3);
JonFreeman 12:a25bdf135348 80
JonFreeman 12:a25bdf135348 81 num += num_add; /* Increase the numerator by the top of the fraction */
JonFreeman 12:a25bdf135348 82 if (num >= den) { /* Check if numerator >= denominator */
JonFreeman 12:a25bdf135348 83 num -= den; /* Calculate the new numerator value */
JonFreeman 12:a25bdf135348 84 x += xinc1; /* Change the x as appropriate */
JonFreeman 12:a25bdf135348 85 y += yinc1; /* Change the y as appropriate */
JonFreeman 12:a25bdf135348 86 }
JonFreeman 12:a25bdf135348 87 x += xinc2; /* Change the x as appropriate */
JonFreeman 12:a25bdf135348 88 y += yinc2; /* Change the y as appropriate */
JonFreeman 12:a25bdf135348 89 }
JonFreeman 12:a25bdf135348 90 //}
JonFreeman 12:a25bdf135348 91 lcd.SetTextColor (save_colour);
JonFreeman 12:a25bdf135348 92 }
JonFreeman 12:a25bdf135348 93
JonFreeman 12:a25bdf135348 94 void moving_coil_meter::LED (int which_led, int colour) { // Meter mounting screw holes serve as LEDs. LCD_COLOR_DARKGRAY for off
JonFreeman 12:a25bdf135348 95 lcd.SetTextColor (colour);
JonFreeman 12:a25bdf135348 96 switch (which_led) {
JonFreeman 12:a25bdf135348 97 case 0: // NW
JonFreeman 12:a25bdf135348 98 lcd.FillCircle (cent_x - screw_hole_offset, cent_y - screw_hole_offset, screw_rad); // panel mounting screw holes near corners
JonFreeman 12:a25bdf135348 99 break;
JonFreeman 12:a25bdf135348 100 case 1: // SW
JonFreeman 12:a25bdf135348 101 lcd.FillCircle (cent_x - screw_hole_offset, cent_y + screw_hole_offset, screw_rad);
JonFreeman 12:a25bdf135348 102 break;
JonFreeman 12:a25bdf135348 103 case 2: // NE
JonFreeman 12:a25bdf135348 104 lcd.FillCircle (cent_x + screw_hole_offset, cent_y - screw_hole_offset, screw_rad);
JonFreeman 12:a25bdf135348 105 break;
JonFreeman 12:a25bdf135348 106 case 3: // SE
JonFreeman 12:a25bdf135348 107 lcd.FillCircle (cent_x + screw_hole_offset, cent_y + screw_hole_offset, screw_rad);
JonFreeman 12:a25bdf135348 108 break;
JonFreeman 12:a25bdf135348 109 default:
JonFreeman 12:a25bdf135348 110 break;
JonFreeman 12:a25bdf135348 111 }
JonFreeman 12:a25bdf135348 112 }
JonFreeman 12:a25bdf135348 113
JonFreeman 12:a25bdf135348 114 void moving_coil_meter::redraw ()
JonFreeman 12:a25bdf135348 115 {
JonFreeman 12:a25bdf135348 116 int oldcolour1 = lcd.GetTextColor ();
JonFreeman 12:a25bdf135348 117 int oldcolour2 = lcd.GetBackColor ();
JonFreeman 12:a25bdf135348 118 lcd.SetTextColor (body_colour);
JonFreeman 12:a25bdf135348 119 // Draw meter body as solid square with rounded corners, complete with mounting screw holes !
JonFreeman 12:a25bdf135348 120
JonFreeman 12:a25bdf135348 121 int font, charwid, x_offset;
JonFreeman 12:a25bdf135348 122 // int corner_rad = (meter_radius / 6),
JonFreeman 12:a25bdf135348 123 // screw_hole_offset = (meter_radius * 92 / 100),
JonFreeman 12:a25bdf135348 124 // screw_rad = (meter_radius / 13);
JonFreeman 12:a25bdf135348 125
JonFreeman 12:a25bdf135348 126 lcd.FillRect (cent_x - meter_radius, cent_y - meter_radius - corner_rad, meter_radius * 2, corner_rad);
JonFreeman 12:a25bdf135348 127 lcd.FillRect (cent_x - meter_radius, cent_y + meter_radius, meter_radius * 2, corner_rad + 1);
JonFreeman 12:a25bdf135348 128 lcd.FillRect (cent_x - meter_radius - corner_rad, cent_y - meter_radius, 1 +(meter_radius + corner_rad) * 2, meter_radius * 2);
JonFreeman 12:a25bdf135348 129 lcd.FillCircle (cent_x - meter_radius, cent_y - meter_radius, corner_rad); // meter box has rounded corners
JonFreeman 12:a25bdf135348 130 lcd.FillCircle (cent_x - meter_radius, cent_y + meter_radius, corner_rad);
JonFreeman 12:a25bdf135348 131 lcd.FillCircle (cent_x + meter_radius, cent_y - meter_radius, corner_rad);
JonFreeman 12:a25bdf135348 132 lcd.FillCircle (cent_x + meter_radius, cent_y + meter_radius, corner_rad); // done drawing meter body
JonFreeman 12:a25bdf135348 133 /* lcd.SetTextColor (LCD_COLOR_DARKGRAY);
JonFreeman 12:a25bdf135348 134 lcd.FillCircle (cent_x - screw_hole_offset, cent_y - screw_hole_offset, screw_rad); // panel mounting screw holes near corners
JonFreeman 12:a25bdf135348 135 lcd.FillCircle (cent_x - screw_hole_offset, cent_y + screw_hole_offset, screw_rad); // Jan 2019 now drawn as LEDs below
JonFreeman 12:a25bdf135348 136 lcd.FillCircle (cent_x + screw_hole_offset, cent_y - screw_hole_offset, screw_rad);
JonFreeman 12:a25bdf135348 137 lcd.FillCircle (cent_x + screw_hole_offset, cent_y + screw_hole_offset, screw_rad);
JonFreeman 12:a25bdf135348 138 */
JonFreeman 12:a25bdf135348 139 lcd.SetTextColor (disc_colour);
JonFreeman 12:a25bdf135348 140 lcd.FillCircle (cent_x, cent_y, meter_radius); // main meter dial face
JonFreeman 12:a25bdf135348 141
JonFreeman 12:a25bdf135348 142 int save_colour = lcd.GetTextColor ();
JonFreeman 12:a25bdf135348 143 int radius_inner = (int) meter_radius - 2, radius_outer = (int) (meter_radius * 0.9);
JonFreeman 12:a25bdf135348 144 double ang, cosang, sinang, angle_step;
JonFreeman 12:a25bdf135348 145 lcd.SetTextColor (scale_colour);
JonFreeman 12:a25bdf135348 146 angle_step = (start_angle - end_angle) / scale_ticks;
JonFreeman 12:a25bdf135348 147 ang = start_angle;
JonFreeman 12:a25bdf135348 148 for (int i = 0; i <= scale_ticks; i++) { // DrawScaleGraduations
JonFreeman 12:a25bdf135348 149 cosang = cos(ang);
JonFreeman 12:a25bdf135348 150 sinang = sin(ang);
JonFreeman 12:a25bdf135348 151 lcd.DrawLine (cent_x + radius_outer * cosang, cent_y - radius_outer * sinang, cent_x + radius_inner * cosang, cent_y - radius_inner * sinang);
JonFreeman 12:a25bdf135348 152 ang -= angle_step;
JonFreeman 12:a25bdf135348 153 }
JonFreeman 12:a25bdf135348 154
JonFreeman 12:a25bdf135348 155 font = get_font_size ();
JonFreeman 12:a25bdf135348 156 charwid = char_widths[font];
JonFreeman 12:a25bdf135348 157 x_offset = charwid * strlen(unit_txt) / 2;
JonFreeman 12:a25bdf135348 158 lcd.SetTextColor (text_colour);
JonFreeman 12:a25bdf135348 159 lcd.SetBackColor (disc_colour);
JonFreeman 12:a25bdf135348 160 displaytext (cent_x - x_offset, cent_y + (meter_radius * 6) / 19, font, unit_txt);
JonFreeman 12:a25bdf135348 161 lcd.SetBackColor (oldcolour2);
JonFreeman 12:a25bdf135348 162 lcd.SetTextColor (oldcolour1);
JonFreeman 12:a25bdf135348 163
JonFreeman 12:a25bdf135348 164 LED (0, LCD_COLOR_RED); // NW
JonFreeman 12:a25bdf135348 165 LED (1, LCD_COLOR_GREEN); // SW
JonFreeman 12:a25bdf135348 166 LED (2, LCD_COLOR_BLUE); // NE
JonFreeman 12:a25bdf135348 167 LED (3, LCD_COLOR_YELLOW); // SE
JonFreeman 12:a25bdf135348 168 }
JonFreeman 12:a25bdf135348 169
JonFreeman 12:a25bdf135348 170
JonFreeman 12:a25bdf135348 171 moving_coil_meter::moving_coil_meter ( int bod_col, int bgcol, int needlecol, int textcol, int scalecol,
JonFreeman 12:a25bdf135348 172 int cx, int cy, int size, double lo, double hi, double start_ang, double end_ang,
JonFreeman 12:a25bdf135348 173 int scaleticks, char * units, int decimal_places, bool sign)
JonFreeman 12:a25bdf135348 174 {
JonFreeman 12:a25bdf135348 175 strncpy (unit_txt, units, 8);
JonFreeman 12:a25bdf135348 176 body_colour = bod_col;
JonFreeman 12:a25bdf135348 177 disc_colour = bgcol;
JonFreeman 12:a25bdf135348 178 needle_colour = needlecol;
JonFreeman 12:a25bdf135348 179 text_colour = textcol;
JonFreeman 12:a25bdf135348 180 scale_colour = scalecol;
JonFreeman 12:a25bdf135348 181 if (size < meter_radius_min)
JonFreeman 12:a25bdf135348 182 size = meter_radius_min;
JonFreeman 12:a25bdf135348 183 if (size > meter_radius_max)
JonFreeman 12:a25bdf135348 184 size = meter_radius_max;
JonFreeman 12:a25bdf135348 185 meter_radius = size;
JonFreeman 12:a25bdf135348 186 cent_x = cx;
JonFreeman 12:a25bdf135348 187 cent_y = cy;
JonFreeman 12:a25bdf135348 188 start_angle = start_ang;
JonFreeman 12:a25bdf135348 189 end_angle = end_ang;
JonFreeman 12:a25bdf135348 190 value_min = lo;
JonFreeman 12:a25bdf135348 191 value_max = hi;
JonFreeman 12:a25bdf135348 192 scale_ticks = scaleticks;
JonFreeman 12:a25bdf135348 193 swept_angle = abs(start_angle - end_angle);
JonFreeman 12:a25bdf135348 194 value_range = (value_max - value_min);
JonFreeman 12:a25bdf135348 195 dec_places = decimal_places;
JonFreeman 12:a25bdf135348 196 draw_sign = sign; // bool
JonFreeman 12:a25bdf135348 197 needle_len = (int)(0.87 * (double)meter_radius);
JonFreeman 12:a25bdf135348 198 corner_rad = (meter_radius / 6),
JonFreeman 12:a25bdf135348 199 screw_hole_offset = (meter_radius * 92 / 100),
JonFreeman 12:a25bdf135348 200 screw_rad = (meter_radius / 13);
JonFreeman 12:a25bdf135348 201 }
JonFreeman 12:a25bdf135348 202
JonFreeman 12:a25bdf135348 203 int moving_coil_meter::get_font_size ()
JonFreeman 12:a25bdf135348 204 {
JonFreeman 12:a25bdf135348 205 int font = meter_radius - meter_radius_min;
JonFreeman 12:a25bdf135348 206 font /= 17;
JonFreeman 12:a25bdf135348 207 if (font > 4)
JonFreeman 12:a25bdf135348 208 font = 4;
JonFreeman 12:a25bdf135348 209 if (font < 2)
JonFreeman 12:a25bdf135348 210 font = 2;
JonFreeman 12:a25bdf135348 211 return font;
JonFreeman 12:a25bdf135348 212 }
JonFreeman 12:a25bdf135348 213
JonFreeman 12:a25bdf135348 214 double anglefix (double a) { // Ensures 0.0 <= angle <= + two PI
JonFreeman 12:a25bdf135348 215 while (a > PI) a -= TWO_PI;
JonFreeman 12:a25bdf135348 216 while (a < 0.0) a += TWO_PI;
JonFreeman 12:a25bdf135348 217 return a;
JonFreeman 12:a25bdf135348 218 }
JonFreeman 12:a25bdf135348 219
JonFreeman 12:a25bdf135348 220 double moving_coil_meter::get_pointer_angle (double v)
JonFreeman 12:a25bdf135348 221 {
JonFreeman 12:a25bdf135348 222 // double a;
JonFreeman 12:a25bdf135348 223 if (v < value_min) v = value_min;
JonFreeman 12:a25bdf135348 224 if (v > value_max) v = value_max;
JonFreeman 12:a25bdf135348 225 return anglefix (start_angle - ((v - value_min) * swept_angle / value_range)) ;
JonFreeman 12:a25bdf135348 226 }
JonFreeman 12:a25bdf135348 227
JonFreeman 12:a25bdf135348 228 void moving_coil_meter::set_value (double meter_read_value)
JonFreeman 12:a25bdf135348 229 {
JonFreeman 12:a25bdf135348 230 char txt[32];
JonFreeman 12:a25bdf135348 231 int x_offset, font, lenchk;//,
JonFreeman 12:a25bdf135348 232 // double pointer_angle;
JonFreeman 12:a25bdf135348 233 DrawNeedle (old_angle, disc_colour); // un-draw needle
JonFreeman 12:a25bdf135348 234 DrawNeedle (get_pointer_angle (meter_read_value), needle_colour) ; // re-draw needle
JonFreeman 12:a25bdf135348 235 if (dec_places == ONE_DP)
JonFreeman 12:a25bdf135348 236 sprintf (txt, " %+.1f \0", meter_read_value);
JonFreeman 12:a25bdf135348 237 else
JonFreeman 12:a25bdf135348 238 sprintf (txt, " %+.0f \0", meter_read_value);
JonFreeman 12:a25bdf135348 239 lenchk = strlen(txt);
JonFreeman 12:a25bdf135348 240 if (!draw_sign) {
JonFreeman 12:a25bdf135348 241 for (int i = 1; i < lenchk; i++)
JonFreeman 12:a25bdf135348 242 txt[i] = txt[i + 1];
JonFreeman 12:a25bdf135348 243 lenchk--; // Stupidly, this gives the display flicker blight
JonFreeman 12:a25bdf135348 244 }
JonFreeman 12:a25bdf135348 245 // lenchk = strlen(txt);// Stupidly, repeating this instead does NOT give the display flicker blight
JonFreeman 12:a25bdf135348 246 font = get_font_size ();
JonFreeman 12:a25bdf135348 247 x_offset = char_widths[font] * lenchk / 2;
JonFreeman 12:a25bdf135348 248 lcd.SetTextColor (text_colour);
JonFreeman 12:a25bdf135348 249 lcd.SetBackColor (disc_colour);
JonFreeman 12:a25bdf135348 250 if (lenchk > 0 && lenchk < 9)
JonFreeman 12:a25bdf135348 251 displaytext (cent_x - x_offset, cent_y + (meter_radius * 11) / 19, font, txt);
JonFreeman 12:a25bdf135348 252 }