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_Meters.ino (10129B)
1 /* 2 Example animated analogue meters using a TFT LCD screen 3 4 Originanally written for a 320 x 240 display, so only occupies half 5 of a 480 x 320 display. 6 7 Needs Font 2 (also Font 4 if using large centered scale label) 8 9 ######################################################################### 10 ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### 11 ######################################################################### 12 */ 13 14 #include <SPI.h> 15 16 #include <TFT_eSPI.h> // Hardware-specific library 17 18 TFT_eSPI tft = TFT_eSPI(); // Invoke custom library 19 20 #define TFT_GREY 0x5AEB 21 22 float ltx = 0; // Saved x coord of bottom of needle 23 uint16_t osx = 120, osy = 120; // Saved x & y coords 24 uint32_t updateTime = 0; // time for next update 25 26 int old_analog = -999; // Value last displayed 27 int old_digital = -999; // Value last displayed 28 29 int value[6] = {0, 0, 0, 0, 0, 0}; 30 int old_value[6] = { -1, -1, -1, -1, -1, -1}; 31 int d = 0; 32 33 void setup(void) { 34 tft.init(); 35 tft.setRotation(1); 36 Serial.begin(57600); // For debug 37 tft.fillScreen(TFT_BLACK); 38 39 analogMeter(); // Draw analogue meter 40 41 // Draw 6 linear meters 42 byte d = 40; 43 plotLinear("A0", 0, 160); 44 plotLinear("A1", 1 * d, 160); 45 plotLinear("A2", 2 * d, 160); 46 plotLinear("A3", 3 * d, 160); 47 plotLinear("A4", 4 * d, 160); 48 plotLinear("A5", 5 * d, 160); 49 50 updateTime = millis(); // Next update time 51 } 52 53 54 void loop() { 55 if (updateTime <= millis()) { 56 updateTime = millis() + 25; // Delay to limit speed of update 57 58 d += 4; if (d >= 360) d = 0; 59 60 //value[0] = map(analogRead(A0), 0, 1023, 0, 100); // Test with value form Analogue 0 61 //value[1] = map(analogRead(A1), 0, 1023, 0, 100); // Test with value form Analogue 1 62 //value[2] = map(analogRead(A2), 0, 1023, 0, 100); // Test with value form Analogue 2 63 //value[3] = map(analogRead(A3), 0, 1023, 0, 100); // Test with value form Analogue 3 64 //value[4] = map(analogRead(A4), 0, 1023, 0, 100); // Test with value form Analogue 4 65 //value[5] = map(analogRead(A5), 0, 1023, 0, 100); // Test with value form Analogue 5 66 67 // Create a Sine wave for testing 68 value[0] = 50 + 50 * sin((d + 0) * 0.0174532925); 69 value[1] = 50 + 50 * sin((d + 60) * 0.0174532925); 70 value[2] = 50 + 50 * sin((d + 120) * 0.0174532925); 71 value[3] = 50 + 50 * sin((d + 180) * 0.0174532925); 72 value[4] = 50 + 50 * sin((d + 240) * 0.0174532925); 73 value[5] = 50 + 50 * sin((d + 300) * 0.0174532925); 74 75 //unsigned long t = millis(); 76 plotPointer(); // It takes aout 3.5ms to plot each gauge for a 1 pixel move, 21ms for 6 gauges 77 78 plotNeedle(value[0], 0); // It takes between 2 and 12ms to replot the needle with zero delay 79 //Serial.println(millis()-t); // Print time taken for meter update 80 } 81 } 82 83 84 // ######################################################################### 85 // Draw the analogue meter on the screen 86 // ######################################################################### 87 void analogMeter() 88 { 89 // Meter outline 90 tft.fillRect(0, 0, 239, 126, TFT_GREY); 91 tft.fillRect(5, 3, 230, 119, TFT_WHITE); 92 93 tft.setTextColor(TFT_BLACK); // Text colour 94 95 // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing) 96 for (int i = -50; i < 51; i += 5) { 97 // Long scale tick length 98 int tl = 15; 99 100 // Coodinates of tick to draw 101 float sx = cos((i - 90) * 0.0174532925); 102 float sy = sin((i - 90) * 0.0174532925); 103 uint16_t x0 = sx * (100 + tl) + 120; 104 uint16_t y0 = sy * (100 + tl) + 140; 105 uint16_t x1 = sx * 100 + 120; 106 uint16_t y1 = sy * 100 + 140; 107 108 // Coordinates of next tick for zone fill 109 float sx2 = cos((i + 5 - 90) * 0.0174532925); 110 float sy2 = sin((i + 5 - 90) * 0.0174532925); 111 int x2 = sx2 * (100 + tl) + 120; 112 int y2 = sy2 * (100 + tl) + 140; 113 int x3 = sx2 * 100 + 120; 114 int y3 = sy2 * 100 + 140; 115 116 // Yellow zone limits 117 //if (i >= -50 && i < 0) { 118 // tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW); 119 // tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW); 120 //} 121 122 // Green zone limits 123 if (i >= 0 && i < 25) { 124 tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_GREEN); 125 tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_GREEN); 126 } 127 128 // Orange zone limits 129 if (i >= 25 && i < 50) { 130 tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_ORANGE); 131 tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_ORANGE); 132 } 133 134 // Short scale tick length 135 if (i % 25 != 0) tl = 8; 136 137 // Recalculate coords incase tick lenght changed 138 x0 = sx * (100 + tl) + 120; 139 y0 = sy * (100 + tl) + 140; 140 x1 = sx * 100 + 120; 141 y1 = sy * 100 + 140; 142 143 // Draw tick 144 tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 145 146 // Check if labels should be drawn, with position tweaks 147 if (i % 25 == 0) { 148 // Calculate label positions 149 x0 = sx * (100 + tl + 10) + 120; 150 y0 = sy * (100 + tl + 10) + 140; 151 switch (i / 25) { 152 case -2: tft.drawCentreString("0", x0, y0 - 12, 2); break; 153 case -1: tft.drawCentreString("25", x0, y0 - 9, 2); break; 154 case 0: tft.drawCentreString("50", x0, y0 - 6, 2); break; 155 case 1: tft.drawCentreString("75", x0, y0 - 9, 2); break; 156 case 2: tft.drawCentreString("100", x0, y0 - 12, 2); break; 157 } 158 } 159 160 // Now draw the arc of the scale 161 sx = cos((i + 5 - 90) * 0.0174532925); 162 sy = sin((i + 5 - 90) * 0.0174532925); 163 x0 = sx * 100 + 120; 164 y0 = sy * 100 + 140; 165 // Draw scale arc, don't draw the last part 166 if (i < 50) tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 167 } 168 169 tft.drawString("%RH", 5 + 230 - 40, 119 - 20, 2); // Units at bottom right 170 tft.drawCentreString("%RH", 120, 70, 4); // Comment out to avoid font 4 171 tft.drawRect(5, 3, 230, 119, TFT_BLACK); // Draw bezel line 172 173 plotNeedle(0, 0); // Put meter needle at 0 174 } 175 176 // ######################################################################### 177 // Update needle position 178 // This function is blocking while needle moves, time depends on ms_delay 179 // 10ms minimises needle flicker if text is drawn within needle sweep area 180 // Smaller values OK if text not in sweep area, zero for instant movement but 181 // does not look realistic... (note: 100 increments for full scale deflection) 182 // ######################################################################### 183 void plotNeedle(int value, byte ms_delay) 184 { 185 tft.setTextColor(TFT_BLACK, TFT_WHITE); 186 char buf[8]; dtostrf(value, 4, 0, buf); 187 tft.drawRightString(buf, 40, 119 - 20, 2); 188 189 if (value < -10) value = -10; // Limit value to emulate needle end stops 190 if (value > 110) value = 110; 191 192 // Move the needle util new value reached 193 while (!(value == old_analog)) { 194 if (old_analog < value) old_analog++; 195 else old_analog--; 196 197 if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0 198 199 float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 200 // Calcualte tip of needle coords 201 float sx = cos(sdeg * 0.0174532925); 202 float sy = sin(sdeg * 0.0174532925); 203 204 // Calculate x delta of needle start (does not start at pivot point) 205 float tx = tan((sdeg + 90) * 0.0174532925); 206 207 // Erase old needle image 208 tft.drawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, TFT_WHITE); 209 tft.drawLine(120 + 20 * ltx, 140 - 20, osx, osy, TFT_WHITE); 210 tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, TFT_WHITE); 211 212 // Re-plot text under needle 213 tft.setTextColor(TFT_BLACK); 214 tft.drawCentreString("%RH", 120, 70, 4); // // Comment out to avoid font 4 215 216 // Store new needle end coords for next erase 217 ltx = tx; 218 osx = sx * 98 + 120; 219 osy = sy * 98 + 140; 220 221 // Draw the needle in the new postion, magenta makes needle a bit bolder 222 // draws 3 lines to thicken needle 223 tft.drawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, TFT_RED); 224 tft.drawLine(120 + 20 * ltx, 140 - 20, osx, osy, TFT_MAGENTA); 225 tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, TFT_RED); 226 227 // Slow needle down slightly as it approaches new postion 228 if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5; 229 230 // Wait before next update 231 delay(ms_delay); 232 } 233 } 234 235 // ######################################################################### 236 // Draw a linear meter on the screen 237 // ######################################################################### 238 void plotLinear(char *label, int x, int y) 239 { 240 int w = 36; 241 tft.drawRect(x, y, w, 155, TFT_GREY); 242 tft.fillRect(x+2, y + 19, w-3, 155 - 38, TFT_WHITE); 243 tft.setTextColor(TFT_CYAN, TFT_BLACK); 244 tft.drawCentreString(label, x + w / 2, y + 2, 2); 245 246 for (int i = 0; i < 110; i += 10) 247 { 248 tft.drawFastHLine(x + 20, y + 27 + i, 6, TFT_BLACK); 249 } 250 251 for (int i = 0; i < 110; i += 50) 252 { 253 tft.drawFastHLine(x + 20, y + 27 + i, 9, TFT_BLACK); 254 } 255 256 tft.fillTriangle(x+3, y + 127, x+3+16, y+127, x + 3, y + 127 - 5, TFT_RED); 257 tft.fillTriangle(x+3, y + 127, x+3+16, y+127, x + 3, y + 127 + 5, TFT_RED); 258 259 tft.drawCentreString("---", x + w / 2, y + 155 - 18, 2); 260 } 261 262 // ######################################################################### 263 // Adjust 6 linear meter pointer positions 264 // ######################################################################### 265 void plotPointer(void) 266 { 267 int dy = 187; 268 byte pw = 16; 269 270 tft.setTextColor(TFT_GREEN, TFT_BLACK); 271 272 // Move the 6 pointers one pixel towards new value 273 for (int i = 0; i < 6; i++) 274 { 275 char buf[8]; dtostrf(value[i], 4, 0, buf); 276 tft.drawRightString(buf, i * 40 + 36 - 5, 187 - 27 + 155 - 18, 2); 277 278 int dx = 3 + 40 * i; 279 if (value[i] < 0) value[i] = 0; // Limit value to emulate needle end stops 280 if (value[i] > 100) value[i] = 100; 281 282 while (!(value[i] == old_value[i])) { 283 dy = 187 + 100 - old_value[i]; 284 if (old_value[i] > value[i]) 285 { 286 tft.drawLine(dx, dy - 5, dx + pw, dy, TFT_WHITE); 287 old_value[i]--; 288 tft.drawLine(dx, dy + 6, dx + pw, dy + 1, TFT_RED); 289 } 290 else 291 { 292 tft.drawLine(dx, dy + 5, dx + pw, dy, TFT_WHITE); 293 old_value[i]++; 294 tft.drawLine(dx, dy - 6, dx + pw, dy - 1, TFT_RED); 295 } 296 } 297 } 298 } 299