#include <DHT.h>
#define DHTPIN 22 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <avr/dtostrf.h>
#define TFT_CS 17
#define TFT_DC 20
#define TFT_RST 21
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// Meter colour schemes
#define RED2RED 0
#define GREEN2GREEN 1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN 5
#define LBLUE2DBLUE 6
#define MIN_TEMP -10
#define MAX_TEMP 30
float h,t;
void setup() {
// put your setup code here, to run once:
Serial1.begin(9600);
// Serial1.println(firsttime);
tft.begin();
dht.begin();
}
void loop() {
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
h = dht.readHumidity();
t = dht.readTemperature();
ringMeter(t,MIN_TEMP,MAX_TEMP,45,5,75,"C",BLUE2RED);
ringMeter(h,0,100,45,155,75,"%",LBLUE2DBLUE);
delay(500);
}
// #########################################################################
// Draw the meter on the screen, returns x coord of righthand side
// #########################################################################
/*
The ringMeter function returns the x coordinate of the right hand side of the meter
to aid placement of the next meter.
int ringMeter(value, vmin, vmax, x, y, r, "Units", scheme)
value is the value to be displayed and plotted, integer values up to 4 digits are accommodated
vmin is the minimum value to be plotted
vmax is the maximum value to be plotted, thus vmin and vmax set the full meter range
x and y are the coordinates of the top left corner of an imaginary box that contains the meter
r in the outer radius of the ring in pixels, the minimum is about 52 before the text intrudes on the ring
"Units" is the text string such as "Volts", "C" etc.
scheme sets the colour scheme, there are some # define statements in the example that enumerate the settings available, others could be added:
#define RED2RED 0
#define GREEN2GREEN 1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN 5
These different schemes set the colour change as the value grows from vmin to vmax, so for example in the following the colour scheme is change from Blue to Red as the value increases:
ringMeter(reading,-10,50, xpos,ypos,radius,"degC",BLUE2RED);
In this case a temperature reading is being plotted in the range -10 to +50 degrees C, as the value increases the segments turn from blue (cold!) to red (hot!) as shown in the picture.
*/
int ringMeter(float 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
int colour = 0;
switch (scheme) {
case 0: colour = ILI9341_RED; break; // Fixed colour
case 1: colour = ILI9341_GREEN; break; // Fixed colour
case 2: colour = ILI9341_BLUE; break; // Fixed colour
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)
case 6: colour = rainbow(map(i, -angle, angle, 30, 0)); break; // lightblue to darkblue
default: colour = ILI9341_BLUE; break; // Fixed colour
}
// 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
tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour);
tft.fillTriangle(x1, y1, x2, y2, x3, y3, colour);
text_colour = colour; // Save the last colour drawn
}
else // Fill in blank segments
{
tft.fillTriangle(x0, y0, x1, y1, x2, y2, ILI9341_DARKGREY);
tft.fillTriangle(x1, y1, x2, y2, x3, y3, ILI9341_DARKGREY);
}
}
// Convert value to a string
char buf[10];
byte len = 4; if (value > 999) len = 5;
dtostrf(value, 5, 1, buf);
// Serial1.println(value);
// Serial1.println(buf);
// Serial1.println("");
// Set the text colour to default
// tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
// Uncomment next line to set the text colour to the last segment value!
// toegevoegd omdat de library Adafruit_GFX geen functie drawCentreString heeft
if (text_colour < 31) {text_colour = ILI9341_DARKGREY;}
tft.setTextColor(text_colour, ILI9341_BLACK);
tft.setTextSize(3);
tft.setCursor(x-50,y-25);
tft.print(buf);
//Serial1.println(x);
//Serial1.println(y);
//Serial1.println("");
tft.setTextColor(text_colour, ILI9341_BLACK);
tft.setTextSize(3);
tft.setCursor(x-5,y+15);
tft.print(units);
//Serial1.println(x);
//Serial1.println(y);
//Serial1.println("");
// Print value, if the meter is large then use big font 6, othewise use 4
//if (r > 84) tft.drawCentreString(buf, x - 5, y - 20, 6); // Value in middle
//else tft.drawCentreString(buf, x - 5, y - 20, 4); // Value in middle
// Print units, if the meter is large then use big font 4, othewise use 2
//tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
//if (r > 84) tft.drawCentreString(units, x, y + 30, 4); // Units display
//else tft.drawCentreString(units, x, y + 5, 2); // Units display
// 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;
}