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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers movingcoilmeter.cpp Source File

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 }