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
movingcoilmeter.cpp
00001 #include "mbed.h" 00002 #include "TS_DISCO_F746NG.h" 00003 #include "LCD_DISCO_F746NG.h" 00004 #include "Electric_Loco.h" 00005 00006 extern LCD_DISCO_F746NG lcd; 00007 static const int char_widths[] = {5, 7, 11, 14, 17, 17} , 00008 meter_radius_min = 30, meter_radius_max = 120; 00009 extern void displaytext (int x, int y, const int font, char * txt) ; 00010 00011 void moving_coil_meter::DrawNeedle (double alpha, int colour) 00012 { 00013 uint16_t x1, x2, x3, y1, y2, y3; 00014 int save_colour, ssa, sca; 00015 while (alpha > PI) alpha -= TWO_PI; 00016 while (alpha < 0.0) alpha += TWO_PI; 00017 double shortln = (needle_len / 18.7), 00018 sina = sin(alpha), 00019 cosa = cos(alpha); 00020 00021 save_colour = lcd.GetTextColor (); 00022 ssa = (int)(shortln * sina); 00023 sca = (int)(shortln * cosa); 00024 old_angle = alpha; 00025 x1 = cent_x - ssa;//(int)(shortln * sin(alpha)); 00026 y1 = cent_y - sca;//(int)(shortln * cos(alpha)); 00027 x2 = cent_x + (int)(needle_len * cosa); 00028 y2 = cent_y - (int)(needle_len * sina); // - as increasing y is downwards 00029 x3 = cent_x + ssa;//(int)(shortln * sin(alpha)); 00030 y3 = cent_y + sca;//(int)(shortln * cos(alpha)); 00031 lcd.SetTextColor (colour); 00032 lcd.FillCircle (cent_x, cent_y, (int)(needle_len / 15.0)); 00033 // FillTriangle (x1, x2, x3, y1, y2, y3); 00034 00035 //static void FillTriangle(uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3) 00036 //{ 00037 int16_t deltax = 0, deltay = 0, x, y, xinc1 = 0, xinc2 = 0, 00038 yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0, 00039 curpixel = 0; 00040 00041 deltax = abs(x2 - x1); /* The difference between the x's */ 00042 deltay = abs(y2 - y1); /* The difference between the y's */ 00043 x = x1; /* Start x off at the first pixel */ 00044 y = y1; /* Start y off at the first pixel */ 00045 00046 if (x2 >= x1) { /* The x-values are increasing */ 00047 xinc1 = 1; 00048 xinc2 = 1; 00049 } else { /* The x-values are decreasing */ 00050 xinc1 = -1; 00051 xinc2 = -1; 00052 } 00053 00054 if (y2 >= y1) { /* The y-values are increasing */ 00055 yinc1 = 1; 00056 yinc2 = 1; 00057 } else { /* The y-values are decreasing */ 00058 yinc1 = -1; 00059 yinc2 = -1; 00060 } 00061 00062 if (deltax >= deltay) { /* There is at least one x-value for every y-value */ 00063 xinc1 = 0; /* Don't change the x when numerator >= denominator */ 00064 yinc2 = 0; /* Don't change the y for every iteration */ 00065 den = deltax; 00066 num = deltax / 2; 00067 num_add = deltay; 00068 num_pixels = deltax; /* There are more x-values than y-values */ 00069 } else { /* There is at least one y-value for every x-value */ 00070 xinc2 = 0; /* Don't change the x for every iteration */ 00071 yinc1 = 0; /* Don't change the y when numerator >= denominator */ 00072 den = deltay; 00073 num = deltay / 2; 00074 num_add = deltax; 00075 num_pixels = deltay; /* There are more y-values than x-values */ 00076 } 00077 00078 for (curpixel = 0; curpixel <= num_pixels; curpixel++) { 00079 lcd.DrawLine(x, y, x3, y3); 00080 00081 num += num_add; /* Increase the numerator by the top of the fraction */ 00082 if (num >= den) { /* Check if numerator >= denominator */ 00083 num -= den; /* Calculate the new numerator value */ 00084 x += xinc1; /* Change the x as appropriate */ 00085 y += yinc1; /* Change the y as appropriate */ 00086 } 00087 x += xinc2; /* Change the x as appropriate */ 00088 y += yinc2; /* Change the y as appropriate */ 00089 } 00090 //} 00091 lcd.SetTextColor (save_colour); 00092 } 00093 00094 void moving_coil_meter::LED (int which_led, int colour) { // Meter mounting screw holes serve as LEDs. LCD_COLOR_DARKGRAY for off 00095 lcd.SetTextColor (colour); 00096 switch (which_led) { 00097 case 0: // NW 00098 lcd.FillCircle (cent_x - screw_hole_offset, cent_y - screw_hole_offset, screw_rad); // panel mounting screw holes near corners 00099 break; 00100 case 1: // SW 00101 lcd.FillCircle (cent_x - screw_hole_offset, cent_y + screw_hole_offset, screw_rad); 00102 break; 00103 case 2: // NE 00104 lcd.FillCircle (cent_x + screw_hole_offset, cent_y - screw_hole_offset, screw_rad); 00105 break; 00106 case 3: // SE 00107 lcd.FillCircle (cent_x + screw_hole_offset, cent_y + screw_hole_offset, screw_rad); 00108 break; 00109 default: 00110 break; 00111 } 00112 } 00113 00114 void moving_coil_meter::redraw () 00115 { 00116 int oldcolour1 = lcd.GetTextColor (); 00117 int oldcolour2 = lcd.GetBackColor (); 00118 lcd.SetTextColor (body_colour); 00119 // Draw meter body as solid square with rounded corners, complete with mounting screw holes ! 00120 00121 int font, charwid, x_offset; 00122 // int corner_rad = (meter_radius / 6), 00123 // screw_hole_offset = (meter_radius * 92 / 100), 00124 // screw_rad = (meter_radius / 13); 00125 00126 lcd.FillRect (cent_x - meter_radius, cent_y - meter_radius - corner_rad, meter_radius * 2, corner_rad); 00127 lcd.FillRect (cent_x - meter_radius, cent_y + meter_radius, meter_radius * 2, corner_rad + 1); 00128 lcd.FillRect (cent_x - meter_radius - corner_rad, cent_y - meter_radius, 1 +(meter_radius + corner_rad) * 2, meter_radius * 2); 00129 lcd.FillCircle (cent_x - meter_radius, cent_y - meter_radius, corner_rad); // meter box has rounded corners 00130 lcd.FillCircle (cent_x - meter_radius, cent_y + meter_radius, corner_rad); 00131 lcd.FillCircle (cent_x + meter_radius, cent_y - meter_radius, corner_rad); 00132 lcd.FillCircle (cent_x + meter_radius, cent_y + meter_radius, corner_rad); // done drawing meter body 00133 /* lcd.SetTextColor (LCD_COLOR_DARKGRAY); 00134 lcd.FillCircle (cent_x - screw_hole_offset, cent_y - screw_hole_offset, screw_rad); // panel mounting screw holes near corners 00135 lcd.FillCircle (cent_x - screw_hole_offset, cent_y + screw_hole_offset, screw_rad); // Jan 2019 now drawn as LEDs below 00136 lcd.FillCircle (cent_x + screw_hole_offset, cent_y - screw_hole_offset, screw_rad); 00137 lcd.FillCircle (cent_x + screw_hole_offset, cent_y + screw_hole_offset, screw_rad); 00138 */ 00139 lcd.SetTextColor (disc_colour); 00140 lcd.FillCircle (cent_x, cent_y, meter_radius); // main meter dial face 00141 00142 int save_colour = lcd.GetTextColor (); 00143 int radius_inner = (int) meter_radius - 2, radius_outer = (int) (meter_radius * 0.9); 00144 double ang, cosang, sinang, angle_step; 00145 lcd.SetTextColor (scale_colour); 00146 angle_step = (start_angle - end_angle) / scale_ticks; 00147 ang = start_angle; 00148 for (int i = 0; i <= scale_ticks; i++) { // DrawScaleGraduations 00149 cosang = cos(ang); 00150 sinang = sin(ang); 00151 lcd.DrawLine (cent_x + radius_outer * cosang, cent_y - radius_outer * sinang, cent_x + radius_inner * cosang, cent_y - radius_inner * sinang); 00152 ang -= angle_step; 00153 } 00154 00155 font = get_font_size (); 00156 charwid = char_widths[font]; 00157 x_offset = charwid * strlen(unit_txt) / 2; 00158 lcd.SetTextColor (text_colour); 00159 lcd.SetBackColor (disc_colour); 00160 displaytext (cent_x - x_offset, cent_y + (meter_radius * 6) / 19, font, unit_txt); 00161 lcd.SetBackColor (oldcolour2); 00162 lcd.SetTextColor (oldcolour1); 00163 00164 LED (0, LCD_COLOR_RED); // NW 00165 LED (1, LCD_COLOR_GREEN); // SW 00166 LED (2, LCD_COLOR_BLUE); // NE 00167 LED (3, LCD_COLOR_YELLOW); // SE 00168 } 00169 00170 00171 moving_coil_meter::moving_coil_meter ( int bod_col, int bgcol, int needlecol, int textcol, int scalecol, 00172 int cx, int cy, int size, double lo, double hi, double start_ang, double end_ang, 00173 int scaleticks, char * units, int decimal_places, bool sign) 00174 { 00175 strncpy (unit_txt, units, 8); 00176 body_colour = bod_col; 00177 disc_colour = bgcol; 00178 needle_colour = needlecol; 00179 text_colour = textcol; 00180 scale_colour = scalecol; 00181 if (size < meter_radius_min) 00182 size = meter_radius_min; 00183 if (size > meter_radius_max) 00184 size = meter_radius_max; 00185 meter_radius = size; 00186 cent_x = cx; 00187 cent_y = cy; 00188 start_angle = start_ang; 00189 end_angle = end_ang; 00190 value_min = lo; 00191 value_max = hi; 00192 scale_ticks = scaleticks; 00193 swept_angle = abs(start_angle - end_angle); 00194 value_range = (value_max - value_min); 00195 dec_places = decimal_places; 00196 draw_sign = sign; // bool 00197 needle_len = (int)(0.87 * (double)meter_radius); 00198 corner_rad = (meter_radius / 6), 00199 screw_hole_offset = (meter_radius * 92 / 100), 00200 screw_rad = (meter_radius / 13); 00201 } 00202 00203 int moving_coil_meter::get_font_size () 00204 { 00205 int font = meter_radius - meter_radius_min; 00206 font /= 17; 00207 if (font > 4) 00208 font = 4; 00209 if (font < 2) 00210 font = 2; 00211 return font; 00212 } 00213 00214 double anglefix (double a) { // Ensures 0.0 <= angle <= + two PI 00215 while (a > PI) a -= TWO_PI; 00216 while (a < 0.0) a += TWO_PI; 00217 return a; 00218 } 00219 00220 double moving_coil_meter::get_pointer_angle (double v) 00221 { 00222 // double a; 00223 if (v < value_min) v = value_min; 00224 if (v > value_max) v = value_max; 00225 return anglefix (start_angle - ((v - value_min) * swept_angle / value_range)) ; 00226 } 00227 00228 void moving_coil_meter::set_value (double meter_read_value) 00229 { 00230 char txt[32]; 00231 int x_offset, font, lenchk;//, 00232 // double pointer_angle; 00233 DrawNeedle (old_angle, disc_colour); // un-draw needle 00234 DrawNeedle (get_pointer_angle (meter_read_value), needle_colour) ; // re-draw needle 00235 if (dec_places == ONE_DP) 00236 sprintf (txt, " %+.1f \0", meter_read_value); 00237 else 00238 sprintf (txt, " %+.0f \0", meter_read_value); 00239 lenchk = strlen(txt); 00240 if (!draw_sign) { 00241 for (int i = 1; i < lenchk; i++) 00242 txt[i] = txt[i + 1]; 00243 lenchk--; // Stupidly, this gives the display flicker blight 00244 } 00245 // lenchk = strlen(txt);// Stupidly, repeating this instead does NOT give the display flicker blight 00246 font = get_font_size (); 00247 x_offset = char_widths[font] * lenchk / 2; 00248 lcd.SetTextColor (text_colour); 00249 lcd.SetBackColor (disc_colour); 00250 if (lenchk > 0 && lenchk < 9) 00251 displaytext (cent_x - x_offset, cent_y + (meter_radius * 11) / 19, font, txt); 00252 }
Generated on Thu Jul 14 2022 06:50:34 by 1.7.2