Аналоговый вольтметр

varvik85
Offline
Зарегистрирован: 28.01.2013

Здравствуйте.Поделитесь пожалуйста примерами исполнения аналогового вольтметра или просто индикатора на tft дисплее интересует именно прорисовка дизайна вольтметра (см рисунок).

MagicianT
Offline
Зарегистрирован: 03.10.2015

/*
 ************************** Analog Meter  *************************
 * Created for  Arduino UNO board
 * TFT: http://www.banggood.com/2_4-Inch-TFT-LCD-Shield-Touch-Board-Display-Modu...
 * UNO + TFT: http://www.banggood.com/UNO-R3-ATmega328P-Board-2_4-Inch-TFT-LCD-Screen-...
 * 
 * CopyLeft 
 * 2015 Anatoly Kuzmenko.
 * k_anatoly@hotmail.com
 *********************************************************************************************
 */

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define LIGHTGREY   0xC618      /* 192, 192, 192 */
#define DARKGREY    0x7BEF      /* 128, 128, 128 */
#define ORANGE  0xFD20

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

uint32_t updateTime = 0;       // time for next update

void setup(void) {
  Serial.begin(115200);
  
           tft.reset();
  uint16_t identifier = tft.readID();
           tft.begin(identifier);
           tft.setRotation( 1); //corr
           tft.fillScreen(BLACK);

  analogMeter(); // Draw analogue meter
  updateTime = millis(); // Next update time
}

void loop()
{
  if (updateTime <= millis()) {
    updateTime = millis() + 500;

    int reading = 0;
    reading = map(analogRead(A5),0,1023,0,100); // Test with value form Analogue 0
    refresh(reading, 8); // Update analogue meter, 8ms delay per needle increment  
    }
}

void analogMeter()
{
  const  char labels[6][4] = {"  0", " 25", " 50", " 75", "100", "%DC"};
  // Meter outline
  tft.fillRect(0, 0, 319, 168, LIGHTGREY);
  tft.fillRect(5, 3, 309, 162, WHITE);  
  tft.setTextColor(BLACK);  // Text colour
  
  // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing)
  for( int i = -50; i < 51; i += 5) {
    // Long scale tick length
    int tl = 20;   
    // Coodinates of tick to draw
    float sx = cos((i - 90) * 0.0174532925);
    float sy = sin((i - 90) * 0.0174532925);
    uint16_t x0 = sx * (133 + tl) + 160;
    uint16_t y0 = sy * (133 + tl) + 187;
    uint16_t x1 = sx * 133 + 160;
    uint16_t y1 = sy * 133 + 187;
    
    // Coordinates of next tick for zone fill
    float sx2 = cos((i + 5 - 90) * 0.0174532925);
    float sy2 = sin((i + 5 - 90) * 0.0174532925);
    int x2 = sx2 * (133 + tl) + 160;
    int y2 = sy2 * (133 + tl) + 187;
    int x3 = sx2 * 133 + 160;
    int y3 = sy2 * 133 + 187;

    // Draw scale arc, don't draw the last part
    if (i < 50) tft.drawLine(x3, y3, x1, y1, BLACK);

    // Yellow zone limits
    if((i >= -50) && (i < 0)) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, YELLOW);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, YELLOW);
      }

    // Green zone limits
    if((i >= 0) && (i < 25)) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, GREEN);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, GREEN);
      }

    // Orange zone limits
    if((i >= 25) && (i < 50)) {
      tft.fillTriangle(x0, y0, x1, y1, x2, y2, ORANGE);
      tft.fillTriangle(x1, y1, x2, y2, x3, y3, ORANGE);
      }
    
    // Short scale tick length
    if (i % 25 != 0) {
      tl = 11; 
      // Recalculate coords incase tick lenght changed
      x0 = sx * (133 + tl) + 160;
      y0 = sy * (133 + tl) + 187;
      }
    // Draw tick
    tft.drawLine(x0, y0, x1, y1, BLACK);
    
    // Check if labels should be drawn, with position tweaks
    if (i % 25 == 0) {
      // Calculate label positions
      x0 = sx * (133 + tl + 10) + 160 -18; //corr
      y0 = sy * (133 + tl + 10) + 187;
      int labp = (i / 25) + 2;
      switch (labp) {
        case 0: tft.setCursor( x0, y0-16); break;
        case 1: tft.setCursor( x0, y0-12); break;
        case 2: tft.setCursor( x0, y0 -8); break;
        case 3: tft.setCursor( x0, y0-12); break;
        case 4: tft.setCursor( x0, y0-16); break;
      }
    tft.setTextColor(BLACK);  tft.setTextSize(2);
    tft.println(labels[labp]);
    }
  }  
  tft.setCursor( 270, 140);
  tft.println(labels[5]);
  
  refresh(0,0); // Put meter needle at 0
}

void refresh(int value, byte ms_delay)
{
  static float ltx = 0;    // Saved x coord of bottom of needle
  static uint16_t osx = 160, osy = 160; // Saved x & y coords0
  static int old_analog =  -999; // Value last displayed

  if (value < -10) value = -10; // Limit value to emulate needle end stops
  if (value > 110) value = 110;

  // Move the needle util new value reached
  while (!(value == old_analog)) {
    if (old_analog < value) old_analog++;
    else old_analog--;
    
    if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0
    
    float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 
    // Calcualte tip of needle coords
    float sx = cos(sdeg * 0.0174532925);
    float sy = sin(sdeg * 0.0174532925);

    // Calculate x delta of needle start (does not start at pivot point)
    float tx = tan((sdeg+90) * 0.0174532925);
    
    // Erase old needle image
    tft.drawLine(160 + (27 * ltx) - 1, 187 - 27, osx - 1, osy, WHITE);
    tft.drawLine(160 + (27 * ltx), 187 - 27, osx, osy, WHITE);
    tft.drawLine(160 + (27 * ltx) + 1, 187 - 27, osx + 1, osy, WHITE);
    
    tft.fillRect( 128, 100, 68, 28, WHITE);
    tft.setTextColor(RED);
    tft.setTextSize(4);  
    tft.setCursor(128, 100);  printNumI( old_analog, 3, '.');
    
    // Store new needle end coords for next erase
    ltx = tx;
    osx = (sx * 130) + 160;
    osy = (sy * 130) + 187;
    
    // Draw the needle in the new postion, magenta makes needle a bit bolder
    // draws 3 lines to thicken needle
    tft.drawLine(160 + (27 * ltx) - 1, 187 - 27, osx - 1, osy, RED);
    tft.drawLine(160 + (27 * ltx), 187 - 27, osx, osy, MAGENTA);
    tft.drawLine(160 + (27 * ltx) + 1, 187 - 27, osx + 1, osy, RED);
    
    // Slow needle down slightly as it approaches new postion
    if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5;
    
    // Wait before next update
    delay(ms_delay);
  }
}

void printNumI( long num, int length, char filler)
{
        static	char buf[25];
        static	char st[27];
        
	boolean neg  = false;
	int c = 0, f = 0;

	if( num == 0 ) {
	  if( length != 0 ) {
            for( c = 0; c < (length -1); c++)  st[c] = filler;
	    st[c]  = 48;
     	    st[c+1]=  0;
	    }
	    else {
	      st[0] = 48;
	      st[1] =  0;
	      }
          }
  	  else {
    	    if( num < 0 ) {
		neg = true;
		num = -num;
		}
  	    while( num > 0 ) {
		buf[c] = 48 + (num % 10);
		c++;
		num = (num -(num % 10))/10;
		}
	    buf[c] = 0;
	    if( neg ) {
		st[0] = 45;
		}
	    if( length > (c + neg) ) {
		for( int i = 0; i < (length -c -neg); i++) {
 		  st[i+neg] = filler;
		  f++;
		  }
		}
	    for( int i = 0; i < c; i++) { st[i+neg+f] = buf[c-i-1]; }
	    st[c+neg+f] = 0;
   	    }
  tft.println( st );
}

 

varvik85
Offline
Зарегистрирован: 28.01.2013

СПАСИБО БОЛЬШОЕ!Еще интересны примеры,в которых отображения сегнала/ов происходит возрастающими/убывающими черточками ( как индикатор уровня громкости)но на TFT,если не трудно,пожалуйста,дайте примерчик