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