Digole
Digital Solutions
iDigole Buyer ProtectioniDigole Buyer
Protection
My shopping cart
0 Items:
Secure Checkout
Top Rated Plus
Visit Our Live Auctions
99.9% Customer's Satisfaction
 
Forum : Digole Serial Display :

 Search Forum.. 
 Creat New Topic   Reply 

Meter Ring on Digole

 Hi Guys

I see a pretty sample of a meter Ring do it for  Alan Senior. The link instructables is : http://www.instructables.com/id/Arduino-analogue-ring-meter-on-colour-TFT-display/?ALLSTEPS

 

The code use very interested thinks :

1) One is the prototype function:

int ringMeter(int value, int vmin, int vmax, int x, int y, int r, char *units, byte scheme). Whit this prototype you can do a lot of visual applications, its very greats

2)They use a triangle form to do the work, but digole doesn´t have this function.

use tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour);

 

I modify the code to adapt to my digole display the code run, but i think that digole can do it more better. I use drawLineTo()  versus fillTringle but is not the same.

You can give me some idea that better?

 

The code:

//Modificacion para digole
#define _Digole_Serial_I2C_
#include <DigoleSerial.h>
#include <Wire.h>
DigoleSerialDisp mydisp(&Wire, '\x27');
 
// Meter colour schemes
#define RED2RED 0
#define GREEN2GREEN 1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN 5
#define ILI9341_GREY 0x2104 // Dark grey 16 bit colour
 
 
uint32_t runTime = -99999;       // time for next update
 
int reading = 0; // Value to be displayed
int d = 0; // Variable used for the sinewave test waveform
 
 
void setup(void) {
  mydisp.begin();
  mydisp.clearScreen();
  mydisp.setRotation(1);
  mydisp.setMode('C'); 
 
}
 
 
void loop() {
  if (millis() - runTime >= 2000L) { // Execute every 2s
    runTime = millis();
 
    // Test with a slowly changing value from a Sine function
    d += 5; if (d >= 360) d = 0;
 
    // Set the the position, gap between meters, and inner radius of the meters
    int xpos = 0, ypos = 5, gap = 4, radius = 52;
 
    // Draw meter and get back x position of next meter
 
    // Test with Sine wave function, normally reading will be from a sensor
    reading = 250 + 250 * sineWave(d + 0);
    xpos = gap + ringMeter(reading, 0, 500, xpos, ypos, radius, "mA", GREEN2RED); // Draw analogue meter
 
    reading = 20 + 30 * sineWave(d + 60);
    xpos = gap + ringMeter(reading, -10, 50, xpos, ypos, radius, "degC", BLUE2RED); // Draw analogue meter
 
    reading = 50 + 50 * sineWave(d + 120);
    ringMeter(reading, 0, 100, xpos, ypos, radius, "%RH", BLUE2BLUE); // Draw analogue meter
 
 
    // Draw two more larger meters
    xpos = 20, ypos = 115, gap = 24, radius = 64;
 
    reading = 1000 + 150 * sineWave(d + 90);
    xpos = gap + ringMeter(reading, 850, 1150, xpos, ypos, radius, "mb", BLUE2RED); // Draw analogue meter
 
    reading = 15 + 15 * sineWave(d + 150);
    xpos = gap + ringMeter(reading, 0, 30, xpos, ypos, radius, "Volts", GREEN2GREEN); // Draw analogue meter
 
    // Draw a large meter
    xpos = 40, ypos = 5, gap = 15, radius = 120;
    reading = 175;
    // Comment out above meters, then uncomment the next line to show large meter
    //ringMeter(reading,0,200, xpos,ypos,radius," Watts",GREEN2RED); // Draw analogue meter
 
  }
}
 
 
// #########################################################################
//  Draw the meter on the screen, returns x coord of righthand side
// #########################################################################
int ringMeter(int value, int vmin, int vmax, int x, int y, int r, char *units, byte scheme)
{
  // Minimum value of r is about 52 before value text intrudes on ring
  // drawing the text first is an option
 
  x += r; y += r;   // Calculate coords of centre of ring
 
  int w = r / 4;    // Width of outer ring is 1/4 of radius
 
  int angle = 150;  // Half the sweep angle of meter (300 degrees)
 
  int text_colour = 0; // To hold the text colour
 
  int v = map(value, vmin, vmax, -angle, angle); // Map the value to an angle v
 
  byte seg = 5; // Segments are 5 degrees wide = 60 segments for 300 degrees
  byte inc = 5; // Draw segments every 5 degrees, increase to 10 for segmented ring
 
  // Draw colour blocks every inc degrees
  for (int i = -angle; i < angle; i += inc) {
 
    // Choose colour from scheme
    //uint8_t colour = 0;
    int colour = 0;
    switch (scheme) {
      case 0: colour = 0xE0; break; //vermell
      case 1: colour = 0x14; break; //Verd
      case 2: colour = 0x03; break; //BLAU
      case 3: colour = rainbow(map(i, -angle, angle, 0, 127)); break; // Full spectrum blue to red
      case 4: colour = rainbow(map(i, -angle, angle, 63, 127)); break; // Green to red (high temperature etc)
      case 5: colour = rainbow(map(i, -angle, angle, 127, 63)); break; // Red to green (low battery etc)
      default: colour = 0x03; break; // Blau
    }
 
    // Calculate pair of coordinates for segment start
    float sx = cos((i - 90) * 0.0174532925);
    float sy = sin((i - 90) * 0.0174532925);
    uint16_t x0 = sx * (r - w) + x;
    uint16_t y0 = sy * (r - w) + y;
    uint16_t x1 = sx * r + x;
    uint16_t y1 = sy * r + y;
 
    // Calculate pair of coordinates for segment end
    float sx2 = cos((i + seg - 90) * 0.0174532925);
    float sy2 = sin((i + seg - 90) * 0.0174532925);
    int x2 = sx2 * (r - w) + x;
    int y2 = sy2 * (r - w) + y;
    int x3 = sx2 * r + x;
    int y3 = sy2 * r + y;
 
 
    if (i < v) { // Fill in coloured segments with 2 triangles
      
      //Posa color
      mydisp.setColor(colour);
      mydisp.drawLineTo(x0, y0);
      mydisp.drawLineTo(x1, y1);
      mydisp.drawLineTo(x2, y2);
      
       //Posa color black El efecte complementari al valo
     // mydisp.setColor(0x00);
      mydisp.drawLineTo(x1, y1);
      mydisp.drawLineTo(x2, y2);
      mydisp.drawLineTo(x3, y3);
      text_colour = colour; // Save the last colour drawn
    }
 
    else // Fill in blank segments
    {
      mydisp.setColor(0x21);
      mydisp.drawLineTo(x0, y0);
      mydisp.drawLineTo(x1, y1);
      mydisp.drawLineTo(x2, y2);
    }
 
  }
 
  // Convert value to a string
  char buf[10];
  byte len = 4; if (value > 999) len = 5;
  dtostrf(value, len, 0, buf);
 
  // Set the text colour to default
  mydisp.setColor(0x0F9);
 
  if (r > 84) mydisp.drawStr(x - 5, y - 20, buf);
  else mydisp.drawStr(x - 5, y - 20, buf);
 
  mydisp.setColor(0x250);
  if (r > 84) mydisp.drawStr(x, y + 30 , units);
  else mydisp.drawStr(x, y + 5 , units);
 
  // Calculate and return right hand side x coordinate
  return x + r;
}
 
// #########################################################################
// Return a 16 bit rainbow colour
// #########################################################################
unsigned int rainbow(byte value)
{
  // Value is expected to be in range 0-127
  // The value is converted to a spectrum colour from 0 = blue through to 127 = red
 
  byte red = 0; // Red is the top 5 bits of a 16 bit colour value
  byte green = 0;// Green is the middle 6 bits
  byte blue = 0; // Blue is the bottom 5 bits
 
  byte quadrant = value / 32;
 
  if (quadrant == 0) {
    blue = 31;
    green = 2 * (value % 32);
    red = 0;
  }
  if (quadrant == 1) {
    blue = 31 - (value % 32);
    green = 63;
    red = 0;
  }
  if (quadrant == 2) {
    blue = 0;
    green = 63;
    red = value % 32;
  }
  if (quadrant == 3) {
    blue = 0;
    green = 63 - 2 * (value % 32);
    red = 31;
  }
  return (red << 11) + (green << 5) + blue;
}
 
// #########################################################################
// Return a value in range -1 to +1 for a given phase angle in degrees
// #########################################################################
float sineWave(int phase) {
  return sin(phase * 0.0174532925);
}

 

 

RE:Meter Ring on Digole

 The images:

http://enrutador.com/IMG_0908.JPG

http://enrutador.com/IMG_0909.JPG

http://enrutador.com/IMG_0910.JPG

Thanks

RE:Meter Ring on Digole

I've adapted the Adafruit fillTriangle code to be used on my Digole OLED 160x128 displays, using the same technique of breaking the triangle down into a series of horizontal lines. I've optimized my version knowing the co-ordinates will never be larger than 8-bits.

I also have a similar ring-drawing functionality but I do it off-line and create a data table with 4 points for 2 triangles (1 polygon) and treat it as a triangle strip (so each addtional triangle is just 1 point). Then in my AVR code, I do something like this and avoid all sin/cos functions and multiplies/divides:

void color_wheel()
{
uint16_t index = 0;
uint8_t hue = 0;

const uint8_t* first = &sOLEDColorWheelTable[0];
uint8_t xpoint0 = VA_READ_PROGMEM_BYTE(first[0]);
uint8_t ypoint0 = VA_READ_PROGMEM_BYTE(first[1]);
uint8_t xpoint1 = VA_READ_PROGMEM_BYTE(first[2]);
uint8_t ypoint1 = VA_READ_PROGMEM_BYTE(first[3]);

// draw the color wheel based on hue values
do
{
// move to the next set of triangles in the table
index += 6;
const uint8_t* table = &sOLEDColorWheelTable[index];

// draw the triangle segments from the inner circle to the outer circle based on the hue's rgb values
uint8_t xpoint2 = VA_READ_PROGMEM_BYTE(table[0]);
uint8_t ypoint2 = VA_READ_PROGMEM_BYTE(table[1]);
uint8_t xpoint3 = VA_READ_PROGMEM_BYTE(table[2]);
uint8_t ypoint3 = VA_READ_PROGMEM_BYTE(table[3]);
uint16_t color = VA_READ_PROGMEM_WORD(table[4]);

// set the color for these segments
OLED.set_color16(color);

// draw the triangle segments
OLED.draw_triangle(xpoint0, ypoint0, xpoint1, ypoint1, xpoint2, ypoint2);
OLED.draw_triangle(xpoint1, ypoint1, xpoint2, ypoint2, xpoint3, ypoint3);

// rotate the points to progress through the triangle strip
xpoint0 = xpoint2;
ypoint0 = ypoint2;
xpoint1 = xpoint3;
ypoint1 = ypoint3;
}
while (++hue != 0);
}

 

RE:Meter Ring on Digole

 thanks Selgus  for sharing your experience and code poetry ¡¡¡¡

Copyright Digole Digital Solutions, 2008-2017. All rights reserved.
Powered by Victor Sun