// GCA901_Nano_voltage_meter
//
// grid voltage variation monitor (230V - 250V AC)
// rolling averaged voltage (of 10 readings) is sent to display
// NOTE: here voltage generated with random function
//
// microcontroller: Arduino Nano
// display 240*240 circular SPI 3.3V TFT with GC9A01 controller
//
// note: random function drives fluctuations of the parameter named 'volt'
// CG9A01 Arduino Nano
// RST -------- NC
// CST -------- 10
// DC --------- 9
// SDA -------- 11 - green wire
// SCL -------- 13 - yellow wire
//
// Floris Wouterlood
// September 1, 2023
// public domain
// made for a 240*240 pixel circular display
// all x-y-coordinates relative to center = x = 120 and y = 120
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_GC9A01A.h"
#define TFT_DC 2
#define TFT_CS 15
Adafruit_GC9A01A tft (TFT_CS, TFT_DC);
#define BLACK 0x0000 // some extra colors
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define ORANGE 0xFBE0
#define GREY 0x84B5
#define BORDEAUX 0xA000
#define AFRICA 0xAB21 // 0xce5f //0xAB21 // current dial color
const int vlez = 34;
#define DEG2RAD 0.0174532925
//int vlez;
int sig = 0;
int multiplier;
int frametime = 100;
int x_pos;
int y_pos;
int center_x = 120; // center x of dial on 240*240 TFT display
int center_y = 120; // center y of dial on 240*240 TFT display
float pivot_x, pivot_y,pivot_x_old, pivot_y_old;
float p1_x,p1_y,p2_x,p2_y,p3_x, p3_y, p4_x, p4_y, p5_x, p5_y;
float p1_x_old,p1_y_old, p2_x_old, p2_y_old, p3_x_old, p3_y_old;
float p4_x_old, p4_y_old, p5_x_old, p5_y_old;
float angleOffset = 3.14;
float arc_x;
float arc_y;
int radius = 120; // center y of circular scale
float angle_circle = 0;
float needleAngle = 0;
int iteration = 0;
int j;
float volt = 220;
int needle_multiplier = 1;
float needle_setter;
float currentNeedleValue = 230; // Start with a base voltage or level
float needleSpeed = 10; // Speed at which the needle returns to the left
// to start with
void setup() {
//randomSeed (analogRead(0));
pinMode(12, OUTPUT);
pinMode(vlez, INPUT);
tft.begin();
Serial.begin (9600);
Serial.println ("");
Serial.println ("");
tft.setRotation (0);
tft.fillScreen (BLACK);
tft.drawCircle (center_x, center_y,120, BLACK);
pivot_x = center_x;
pivot_y = center_y+50;
p1_x_old = center_x; p1_y_old = center_y+50;
p2_x_old = center_x; p2_y_old = center_y+50;
p3_x_old = center_x; p3_y_old = center_y+50;
p4_x_old = center_x; p4_y_old = center_y+50;
p5_x_old = center_x; p5_y_old = center_y+30;
create_dial ();
needle_setter = volt;
needleAngle = (((needle_setter)*DEG2RAD*1.8)-3.14);
needle();
draw_pivot ();
}
void loop (){
// Map the analog input (voltage) to the needle range
float targetNeedleValue = map(analogRead(vlez), 0, 400, 230, 270);
Serial.println(targetNeedleValue);
sig = analogRead(vlez);
if (sig > 280) {digitalWrite(12, HIGH);} else {digitalWrite(12, LOW);}
// If the target value is greater than the current needle position, move quickly
if (targetNeedleValue > currentNeedleValue) {
currentNeedleValue = targetNeedleValue;
}
// If the target value is lower, move more slowly to simulate damping
else if (targetNeedleValue < currentNeedleValue) {
currentNeedleValue -= needleSpeed; // Decrease the value gradually
if (currentNeedleValue < targetNeedleValue) {
currentNeedleValue = targetNeedleValue; // Ensure we don't overshoot
}
}
// Update the needle position
needle_setter = currentNeedleValue;
needle();
draw_pivot();
delay(frametime); // Control the update rate
}
void needle (){ // dynamic needle management
tft.drawLine (pivot_x, pivot_y, p1_x_old, p1_y_old, AFRICA); // remove old needle
tft.fillTriangle (p1_x_old, p1_y_old, p2_x_old, p2_y_old, p3_x_old, p3_y_old, AFRICA); // remove old arrow head
tft.fillTriangle (pivot_x, pivot_y, p4_x_old, p4_y_old, p5_x_old, p5_y_old, AFRICA); // remove old arrow head
needleAngle = (((needle_setter)*0.01745331*1.8)-3.14);
p1_x = (pivot_x + ((radius)*cos(needleAngle))); // needle tip
p1_y = (pivot_y + ((radius)*sin(needleAngle)));
p2_x = (pivot_x + ((radius-15)*cos(needleAngle-0.05))); // needle triange left
p2_y = (pivot_y + ((radius-15)*sin(needleAngle-0.05)));
p3_x = (pivot_x + ((radius-15)*cos(needleAngle+0.05))); // needle triange right
p3_y = (pivot_y + ((radius-15)*sin(needleAngle+0.05)));
p4_x = (pivot_x + ((radius-90)*cos(angleOffset+(needleAngle-0.2)))); // needle triange left
p4_y = (pivot_y + ((radius-90)*sin(angleOffset+(needleAngle-0.2))));
p5_x = (pivot_x + ((radius-90)*cos(angleOffset+(needleAngle+0.2)))); // needle triange right
p5_y = (pivot_y + ((radius-90)*sin(angleOffset+(needleAngle+0.2))));
p1_x_old = p1_x; p1_y_old = p1_y; // remember previous needle position
p2_x_old = p2_x; p2_y_old = p2_y;
p3_x_old = p3_x; p3_y_old = p3_y;
p4_x_old = p4_x; p4_y_old = p4_y; // remember previous needle counterweight position
p5_x_old = p5_x; p5_y_old = p5_y;
tft.drawLine (pivot_x, pivot_y, p1_x, p1_y, BLACK); // create needle
tft.fillTriangle (p1_x, p1_y, p2_x, p2_y, p3_x, p3_y, BLACK); // create needle tip pointer
// tft.drawLine (center_x-80, center_y+70, center_x+80,center_y+70, BLACK); // repair floor
tft.fillTriangle (pivot_x, pivot_y, p4_x, p4_y, p5_x, p5_y, BLACK); // create needle counterweight
}
void create_dial (){
tft.fillCircle (center_x, center_y,120, AFRICA); // general dial field
tft.drawCircle (center_x, center_y,118,GREY);
tft.drawCircle (center_x, center_y,117,BLACK);
tft.drawCircle (center_x, center_y,116,BLACK);
tft.drawCircle (center_x, center_y,115,GREY);
for (j= 30; j<60 ; j+=5)
{
needleAngle = ((j*DEG2RAD*1.8)-3.14);
arc_x = (pivot_x + ((radius+15)*cos(needleAngle))); // needle tip
arc_y = (pivot_y + ((radius+15)*sin(needleAngle)));
tft.drawPixel (arc_x,arc_y, BLACK);
tft.fillCircle (arc_x,arc_y,2, BLACK);
}
for (j= 60; j<75 ; j+=5)
{
needleAngle = ((j*DEG2RAD*1.8)-3.14);
arc_x = (pivot_x + ((radius+15)*cos(needleAngle))); // needle tip
arc_y = (pivot_y + ((radius+15)*sin(needleAngle)));
tft.drawPixel (arc_x,arc_y, RED);
tft.fillCircle (arc_x,arc_y,2, RED);
}
tft.setTextColor (BLACK,AFRICA);
tft.setTextSize (4);
tft.setCursor (center_x+55, center_y+40);
tft.print ("L");
tft.setTextSize (4);
tft.setCursor (center_x-70, center_y+40);
tft.print ("VU");
// tft.drawLine (center_x-80, center_y+70, center_x+80,center_y+70, WHITE); // create floor
}
void draw_pivot (){
tft.fillCircle (pivot_x, pivot_y,8,RED);
tft.drawCircle (pivot_x, pivot_y,8,BLACK);
tft.drawCircle (pivot_x, pivot_y,3,BLACK);
}
Comments
Please log in or sign up to comment.