Digole
©DIGITAL
SOLUTIONS

Serial Display emulator    New Display User manual

Forum login or
Login:
Password:
  
Forum Catagory
Digole Serial Display (215)
  12864 LCD/OLED module (24)
  24064 LCD module (3)
  Color LCD Modules (29)
  Color OLED module (21)
  Online Emulater (5)
  Universal GLCD module (1)
  Universal Text LCD module (2)
Mini Display Panels (0)
  Mini LCDs (0)
  Mini OLEDs (0)
Pattern Drive Module (0)
~Buy & Sell on Digole (2)
~Others~ (5)
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/Digole Technologies Inc., 2008-2026. All rights reserved.
Powered by Digole