/* ESP32 Multiple Blocks
Displays several cells with different information, 3rd cell still WIP
*/
#include <TFT_eSPI.h>
#include <SPI.h> // this is needed for display
#include "Free_Fonts.h"
// The display also uses hardware SPI, plus #9 & #10
#define TFT_CS 15
#define TFT_DC 2
#define TFT_MOSI 23
#define TFT_SCLK 18
#define color1 0xF79E
#define color2 0xB1B1
#define color3 0x4A69
#define TFT_GREY 0x5AEB
#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height
TFT_eSprite sprite = TFT_eSprite(&tft);
TFT_eSprite cell1Sprite = TFT_eSprite(&tft);
TFT_eSprite cell2Sprite = TFT_eSprite(&tft);
TFT_eSprite cell3Sprite = TFT_eSprite(&tft);
TFT_eSprite cell4Sprite = TFT_eSprite(&tft);
#define SCREEN_WIDTH tft.width()
#define SCREEN_HEIGHT tft.height()
// Cell bounds
#define cell_1_min_x 1
#define cell_1_max_x (SCREEN_WIDTH / 3) - 1
#define cell_1_min_y 1
#define cell_1_max_y (SCREEN_HEIGHT / 2) - 1
#define cell_1_width cell_1_max_x - cell_1_min_x
#define cell_1_height cell_1_max_y - cell_1_min_y
#define M_SIZE 0.667
#define cell_2_min_x (SCREEN_WIDTH / 3) + 1
#define cell_2_max_x SCREEN_WIDTH - 1
#define cell_2_min_y 1
#define cell_2_max_y (SCREEN_HEIGHT / 2) - 1
#define cell_3_min_x 1
#define cell_3_max_x (SCREEN_WIDTH / 3) - 1
#define cell_3_min_y (SCREEN_HEIGHT / 2) + 1
#define cell_3_max_y SCREEN_HEIGHT - 1
#define cell_4_min_x (SCREEN_WIDTH / 3) + 1
#define cell_4_max_x SCREEN_WIDTH - 1
#define cell_4_min_y (SCREEN_HEIGHT / 2) + 1
#define cell_4_max_y SCREEN_HEIGHT - 1
#define cell_4_width cell_4_max_x - cell_4_min_x
#define cell_4_height cell_4_max_y - cell_4_min_y
void setup(void) {
Serial.begin(115200);
tft.begin();
tft.setRotation(1);
Serial.println("TFT set up");
cell1Sprite.createSprite(cell_1_max_x - cell_1_min_x, cell_1_max_y - cell_1_min_y);
cell2Sprite.createSprite(cell_2_max_x - cell_2_min_x, cell_2_max_y - cell_2_min_y);
cell3Sprite.createSprite(cell_3_max_x - cell_3_min_x, cell_3_max_y - cell_3_min_y);
cell4Sprite.createSprite(cell_4_width, cell_4_height);
Serial.println(SCREEN_WIDTH);
Serial.println(SCREEN_HEIGHT);
tft.fillRect(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, 1, TFT_WHITE);
tft.fillRect(0, 0, 1, SCREEN_WIDTH, TFT_WHITE);
tft.fillRect(SCREEN_WIDTH / 3, 0, 1, SCREEN_WIDTH, TFT_WHITE);
setupCell2();
}
int timer = 0;
void loop() {
// delay(100);
timer++;
if (timer > 60) {
timer = 0;
}
renderCell1Frame();
renderCell2Frame();
renderCell3Frame();
renderCell4Frame();
}
void setupCell1() {
Serial.println("Setting up temperature section in cell 1");
int xpos = 8;
int ypos = 8;
int yPad = 16;
float dispTemp = (float)random(1, 80)/(float)(80/1);
int padding = cell1Sprite.textWidth(String(dispTemp, 1), FONT4);
cell1Sprite.setTextDatum(TL_DATUM);
cell1Sprite.drawString("TEMP", xpos, ypos, FONT2);
cell1Sprite.setTextDatum(TR_DATUM);
cell1Sprite.drawString("`C", cell_1_width - xpos, ypos, FONT2);
cell1Sprite.setTextDatum(TL_DATUM);
cell1Sprite.setTextPadding(padding);
ypos += cell1Sprite.fontHeight(FONT4) / 2 + yPad;
cell1Sprite.drawFloat(dispTemp, 1, (cell_1_width - padding) / 2, ypos, FONT4);
cell1Sprite.setTextPadding(0);
cell1Sprite.pushSprite(cell_1_min_x, cell_1_min_y);
}
void renderCell1Frame() {
if (timer != 1) {
return;
}
setupCell1();
}
void setupCell2() {
Serial.println("Setting up analog meter in cell 2");
cell2Sprite.fillSprite(TFT_WHITE);
cell2Sprite.fillRect(0, 0, M_SIZE*239, M_SIZE*131, TFT_GREY);
cell2Sprite.fillRect(1, M_SIZE*3, M_SIZE*234, M_SIZE*125, TFT_WHITE);
cell2Sprite.setTextColor(TFT_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 = 15;
// Coordinates of tick to draw
float sx = cos((i - 90) * 0.0174532925);
float sy = sin((i - 90) * 0.0174532925);
uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120;
uint16_t y0 = sy * (M_SIZE*100 + tl) + M_SIZE*150;
uint16_t x1 = sx * M_SIZE*100 + M_SIZE*120;
uint16_t y1 = sy * M_SIZE*100 + M_SIZE*150;
// 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 * (M_SIZE*100 + tl) + M_SIZE*120;
int y2 = sy2 * (M_SIZE*100 + tl) + M_SIZE*150;
int x3 = sx2 * M_SIZE*100 + M_SIZE*120;
int y3 = sy2 * M_SIZE*100 + M_SIZE*150;
// Yellow zone limits
//if (i >= -50 && i < 0) {
// tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW);
// tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW);
//}
// Green zone limits
if (i >= 0 && i < 25) {
cell2Sprite.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_GREEN);
cell2Sprite.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_GREEN);
}
// Orange zone limits
if (i >= 25 && i < 50) {
cell2Sprite.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_ORANGE);
cell2Sprite.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_ORANGE);
}
// Short scale tick length
if (i % 25 != 0) tl = 8;
// Recalculate coords incase tick lenght changed
x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120;
y0 = sy * (M_SIZE*100 + tl) + M_SIZE*150;
x1 = sx * M_SIZE*100 + M_SIZE*120;
y1 = sy * M_SIZE*100 + M_SIZE*150;
// Draw tick
cell2Sprite.drawLine(x0, y0, x1, y1, TFT_BLACK);
// Check if labels should be drawn, with position tweaks
if (i % 25 == 0) {
// Calculate label positions
x0 = sx * (M_SIZE*100 + tl + 10) + M_SIZE*120;
y0 = sy * (M_SIZE*100 + tl + 10) + M_SIZE*150;
switch (i / 25) {
case -2: cell2Sprite.drawCentreString("0", x0+4, y0-4, 1); break;
case -1: cell2Sprite.drawCentreString("25", x0+2, y0, 1); break;
case 0: cell2Sprite.drawCentreString("50", x0, y0, 1); break;
case 1: cell2Sprite.drawCentreString("75", x0, y0, 1); break;
case 2: cell2Sprite.drawCentreString("100", x0-2, y0-4, 1); break;
}
}
// Now draw the arc of the scale
sx = cos((i + 5 - 90) * 0.0174532925);
sy = sin((i + 5 - 90) * 0.0174532925);
x0 = sx * M_SIZE*100 + M_SIZE*120;
y0 = sy * M_SIZE*100 + M_SIZE*150;
// Draw scale arc, don't draw the last part
if (i < 50) cell2Sprite.drawLine(x0, y0, x1, y1, TFT_BLACK);
}
cell2Sprite.drawString("%RH", M_SIZE*(3 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right
cell2Sprite.drawCentreString("%RH", M_SIZE*120, M_SIZE*75, 4); // Comment out to avoid font 4
cell2Sprite.drawRect(1, M_SIZE*3, M_SIZE*236, M_SIZE*126, TFT_BLACK); // Draw bezel line
plotNeedle(0, 0); // Put meter needle at 0
}
float ltx = 0; // Saved x coord of bottom of needle
uint16_t osx = M_SIZE*120, osy = M_SIZE*120; // Saved x & y coords
int old_analog = -999; // Value last displayed
void plotNeedle(int value, byte ms_delay) {
cell2Sprite.setTextColor(TFT_BLACK, TFT_WHITE);
char buf[8]; dtostrf(value, 4, 0, buf);
cell2Sprite.drawRightString(buf, 33, M_SIZE*(119 - 20), 2);
if (value < -10) value = -10; // Limit value to emulate needle end stops
if (value > 110) value = 110;
// Move the needle until 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 if delay is 0
float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle
// Calculate 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
cell2Sprite.drawLine(M_SIZE*(120 + 24 * ltx) - 1, M_SIZE*(150 - 24), osx - 1, osy, TFT_WHITE);
cell2Sprite.drawLine(M_SIZE*(120 + 24 * ltx), M_SIZE*(150 - 24), osx, osy, TFT_WHITE);
cell2Sprite.drawLine(M_SIZE*(120 + 24 * ltx) + 1, M_SIZE*(150 - 24), osx + 1, osy, TFT_WHITE);
// Re-plot text under needle
cell2Sprite.setTextColor(TFT_BLACK, TFT_WHITE);
cell2Sprite.drawCentreString("%RH", M_SIZE*120, M_SIZE*75, 4); // // Comment out to avoid font 4
// Store new needle end coords for next erase
ltx = tx;
osx = M_SIZE*(sx * 98 + 120);
osy = M_SIZE*(sy * 98 + 150);
// Draw the needle in the new postion, magenta makes needle a bit bolder
// draws 3 lines to thicken needle
cell2Sprite.drawLine(M_SIZE*(120 + 24 * ltx) - 1, M_SIZE*(150 - 24), osx - 1, osy, TFT_RED);
cell2Sprite.drawLine(M_SIZE*(120 + 24 * ltx), M_SIZE*(150 - 24), osx, osy, TFT_MAGENTA);
cell2Sprite.drawLine(M_SIZE*(120 + 24 * ltx) + 1, M_SIZE*(150 - 24), osx + 1, osy, TFT_RED);
// Slow needle down slightly as it approaches new postion
if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5;
cell2Sprite.pushSprite(cell_2_min_x, cell_2_min_y);
delay(ms_delay);
}
}
int value[6] = {0, 0, 0, 0, 0, 0};
int old_value[6] = { -1, -1, -1, -1, -1, -1};
int d = 0;
uint32_t updateTime = 0; // time for next update
void renderCell2Frame() {
if (updateTime <= millis()) {
updateTime = millis() + 35;
d += 4; if (d >= 360) d = 0;
value[0] = 50 + 50 * sin((d + 0) * 0.0174532925);
plotNeedle(value[0], 0);
}
}
void renderCell3Frame() {
cell3Sprite.fillSprite(TFT_RED);
cell3Sprite.pushSprite(cell_3_min_x, cell_3_min_y);
}
String week[7]= { "MON","TUE","WED","THU","FRI","SAT","SUN" };
int values[7]= { 0 };
int sum = 0;
float average = 0.00;
void setupCell4() {
Serial.println("Setting up bar graph in cell 4");
cell4Sprite.fillSprite(color3);
cell4Sprite.fillRect(10, 20, cell_4_width - 20, cell_4_height - 25, color1);
cell4Sprite.fillRoundRect(20, 15, cell_4_width - 40, cell_4_height - 40, 5, color2);
cell4Sprite.fillRect(40, 25, 2, 50, color1); // display y axis bar
cell4Sprite.fillRect(40, 75, cell_4_width - 70, 2, color1); // display x axis bar
cell4Sprite.setTextDatum(4);
cell4Sprite.setTextColor(color1, color2);
for(int i=2;i<8;i=i+2){
cell4Sprite.drawString(String(i*10), 30, 75-(i*7)); // display labels on the y axis
for(int j=0;j<cell_4_width - 70;j=j+5) {
cell4Sprite.drawPixel(40+j,75-(i*7),color1); // displays dots on the bar graph
}
}
sum=0;
for(int i=0;i<7;i++){
cell4Sprite.drawString(week[i], 60+(i*20), 85); // displays labels on the x axis
values[i] = random(5, 60);
sum = sum+values[i];
cell4Sprite.fillRect(56+(i*20), 75-values[i], 8, values[i], color1); // displays the bars on the graph
}
average=sum/7.00;
cell4Sprite.setTextDatum(0);
cell4Sprite.setTextColor(color3,color1);
cell4Sprite.drawString("SUM= "+String(sum), 20, 95, 2);
cell4Sprite.drawString("AVERAGE= "+String(average), 90, 95, 2);
cell4Sprite.setTextColor(color1, color3);
cell4Sprite.drawString("EARNINGS $", 20, 0, 2);
cell4Sprite.pushSprite(cell_4_min_x, cell_4_min_y);
}
void renderCell4Frame() {
if (timer != 1) {
return;
}
setupCell4();
}