acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
TFT_Meter_linear.ino (7488B)
1 /* 2 An example analogue meter using a ILI9341 TFT LCD screen 3 4 Needs Font 2 (also Font 4 if using large scale label) 5 6 Make sure all the display driver and pin connections are correct by 7 editing the User_Setup.h file in the TFT_eSPI library folder. 8 9 ######################################################################### 10 ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### 11 ######################################################################### 12 13 Updated by Bodmer for variable meter size 14 */ 15 16 // Define meter size as 1 for tft.rotation(0) or 1.3333 for tft.rotation(1) 17 #define M_SIZE 1.3333 18 19 #include <TFT_eSPI.h> // Hardware-specific library 20 #include <SPI.h> 21 22 TFT_eSPI tft = TFT_eSPI(); // Invoke custom library 23 24 #define TFT_GREY 0x5AEB 25 26 float ltx = 0; // Saved x coord of bottom of needle 27 uint16_t osx = M_SIZE*120, osy = M_SIZE*120; // Saved x & y coords 28 uint32_t updateTime = 0; // time for next update 29 30 int old_analog = -999; // Value last displayed 31 32 int value[6] = {0, 0, 0, 0, 0, 0}; 33 int old_value[6] = { -1, -1, -1, -1, -1, -1}; 34 int d = 0; 35 36 void setup(void) { 37 tft.init(); 38 tft.setRotation(1); 39 Serial.begin(57600); // For debug 40 tft.fillScreen(TFT_BLACK); 41 42 analogMeter(); // Draw analogue meter 43 44 updateTime = millis(); // Next update time 45 } 46 47 48 void loop() { 49 if (updateTime <= millis()) { 50 updateTime = millis() + 35; // Update emter every 35 milliseconds 51 52 // Create a Sine wave for testing 53 d += 4; if (d >= 360) d = 0; 54 value[0] = 50 + 50 * sin((d + 0) * 0.0174532925); 55 56 plotNeedle(value[0], 0); // It takes between 2 and 12ms to replot the needle with zero delay 57 } 58 } 59 60 61 // ######################################################################### 62 // Draw the analogue meter on the screen 63 // ######################################################################### 64 void analogMeter() 65 { 66 67 // Meter outline 68 tft.fillRect(0, 0, M_SIZE*239, M_SIZE*126, TFT_GREY); 69 tft.fillRect(5, 3, M_SIZE*230, M_SIZE*119, TFT_WHITE); 70 71 tft.setTextColor(TFT_BLACK); // Text colour 72 73 // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing) 74 for (int i = -50; i < 51; i += 5) { 75 // Long scale tick length 76 int tl = 15; 77 78 // Coodinates of tick to draw 79 float sx = cos((i - 90) * 0.0174532925); 80 float sy = sin((i - 90) * 0.0174532925); 81 uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; 82 uint16_t y0 = sy * (M_SIZE*100 + tl) + M_SIZE*140; 83 uint16_t x1 = sx * M_SIZE*100 + M_SIZE*120; 84 uint16_t y1 = sy * M_SIZE*100 + M_SIZE*140; 85 86 // Coordinates of next tick for zone fill 87 float sx2 = cos((i + 5 - 90) * 0.0174532925); 88 float sy2 = sin((i + 5 - 90) * 0.0174532925); 89 int x2 = sx2 * (M_SIZE*100 + tl) + M_SIZE*120; 90 int y2 = sy2 * (M_SIZE*100 + tl) + M_SIZE*140; 91 int x3 = sx2 * M_SIZE*100 + M_SIZE*120; 92 int y3 = sy2 * M_SIZE*100 + M_SIZE*140; 93 94 // Yellow zone limits 95 //if (i >= -50 && i < 0) { 96 // tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW); 97 // tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW); 98 //} 99 100 // Green zone limits 101 if (i >= 0 && i < 25) { 102 tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_GREEN); 103 tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_GREEN); 104 } 105 106 // Orange zone limits 107 if (i >= 25 && i < 50) { 108 tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_ORANGE); 109 tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_ORANGE); 110 } 111 112 // Short scale tick length 113 if (i % 25 != 0) tl = 8; 114 115 // Recalculate coords incase tick lenght changed 116 x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; 117 y0 = sy * (M_SIZE*100 + tl) + M_SIZE*140; 118 x1 = sx * M_SIZE*100 + M_SIZE*120; 119 y1 = sy * M_SIZE*100 + M_SIZE*140; 120 121 // Draw tick 122 tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 123 124 // Check if labels should be drawn, with position tweaks 125 if (i % 25 == 0) { 126 // Calculate label positions 127 x0 = sx * (M_SIZE*100 + tl + 10) + M_SIZE*120; 128 y0 = sy * (M_SIZE*100 + tl + 10) + M_SIZE*140; 129 switch (i / 25) { 130 case -2: tft.drawCentreString("0", x0, y0 - 12, 2); break; 131 case -1: tft.drawCentreString("25", x0, y0 - 9, 2); break; 132 case 0: tft.drawCentreString("50", x0, y0 - 7, 2); break; 133 case 1: tft.drawCentreString("75", x0, y0 - 9, 2); break; 134 case 2: tft.drawCentreString("100", x0, y0 - 12, 2); break; 135 } 136 } 137 138 // Now draw the arc of the scale 139 sx = cos((i + 5 - 90) * 0.0174532925); 140 sy = sin((i + 5 - 90) * 0.0174532925); 141 x0 = sx * M_SIZE*100 + M_SIZE*120; 142 y0 = sy * M_SIZE*100 + M_SIZE*140; 143 // Draw scale arc, don't draw the last part 144 if (i < 50) tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 145 } 146 147 tft.drawString("%RH", M_SIZE*(5 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right 148 tft.drawCentreString("%RH", M_SIZE*120, M_SIZE*70, 4); // Comment out to avoid font 4 149 tft.drawRect(5, 3, M_SIZE*230, M_SIZE*119, TFT_BLACK); // Draw bezel line 150 151 plotNeedle(0, 0); // Put meter needle at 0 152 } 153 154 // ######################################################################### 155 // Update needle position 156 // This function is blocking while needle moves, time depends on ms_delay 157 // 10ms minimises needle flicker if text is drawn within needle sweep area 158 // Smaller values OK if text not in sweep area, zero for instant movement but 159 // does not look realistic... (note: 100 increments for full scale deflection) 160 // ######################################################################### 161 void plotNeedle(int value, byte ms_delay) 162 { 163 tft.setTextColor(TFT_BLACK, TFT_WHITE); 164 char buf[8]; dtostrf(value, 4, 0, buf); 165 tft.drawRightString(buf, M_SIZE*40, M_SIZE*(119 - 20), 2); 166 167 if (value < -10) value = -10; // Limit value to emulate needle end stops 168 if (value > 110) value = 110; 169 170 // Move the needle until new value reached 171 while (!(value == old_analog)) { 172 if (old_analog < value) old_analog++; 173 else old_analog--; 174 175 if (ms_delay == 0) old_analog = value; // Update immediately if delay is 0 176 177 float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 178 // Calcualte tip of needle coords 179 float sx = cos(sdeg * 0.0174532925); 180 float sy = sin(sdeg * 0.0174532925); 181 182 // Calculate x delta of needle start (does not start at pivot point) 183 float tx = tan((sdeg + 90) * 0.0174532925); 184 185 // Erase old needle image 186 tft.drawLine(M_SIZE*(120 + 20 * ltx - 1), M_SIZE*(140 - 20), osx - 1, osy, TFT_WHITE); 187 tft.drawLine(M_SIZE*(120 + 20 * ltx), M_SIZE*(140 - 20), osx, osy, TFT_WHITE); 188 tft.drawLine(M_SIZE*(120 + 20 * ltx + 1), M_SIZE*(140 - 20), osx + 1, osy, TFT_WHITE); 189 190 // Re-plot text under needle 191 tft.setTextColor(TFT_BLACK); 192 tft.drawCentreString("%RH", M_SIZE*120, M_SIZE*70, 4); // // Comment out to avoid font 4 193 194 // Store new needle end coords for next erase 195 ltx = tx; 196 osx = M_SIZE*(sx * 98 + 120); 197 osy = M_SIZE*(sy * 98 + 140); 198 199 // Draw the needle in the new postion, magenta makes needle a bit bolder 200 // draws 3 lines to thicken needle 201 tft.drawLine(M_SIZE*(120 + 20 * ltx - 1), M_SIZE*(140 - 20), osx - 1, osy, TFT_RED); 202 tft.drawLine(M_SIZE*(120 + 20 * ltx), M_SIZE*(140 - 20), osx, osy, TFT_MAGENTA); 203 tft.drawLine(M_SIZE*(120 + 20 * ltx + 1), M_SIZE*(140 - 20), osx + 1, osy, TFT_RED); 204 205 // Slow needle down slightly as it approaches new postion 206 if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5; 207 208 // Wait before next update 209 delay(ms_delay); 210 } 211 } 212