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