#include "SPI.h"
#include "TFT_eSPI.h"
#include "User_Setup.h"
#include <WiFi.h>
#include <HTTPClient.h>
// include the header file attached to this sketch - part of TFT_eSPI package
#include "Free_Fonts.h"
#include "zCalibri48.h"
#include "zCalibri24.h"
#include "calibri72.h"
#include "MoonRise.h"
#include <TimeLib.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
WiFiUDP ntpUDP;
// By default 'pool.ntp.org' is used with 60 seconds update interval and no offset
NTPClient timeClient(ntpUDP);
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft);
TFT_eSprite moon_prev = TFT_eSprite(&tft);
TFT_eSprite moon_cur = TFT_eSprite(&tft);
TFT_eSprite moon_next = TFT_eSprite(&tft);
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define GREY 0x2108
#define COLOR_CLOCK 0xFDC1
#define COLOR_MOON 0xFFA6
#define SCALE0 0xC655 // accent color for unused scale segments
#define SCALE1 0x5DEE // accent color for unused scale segments
#define TEXT_COLOR 0xFFFF // is currently white
// rainbow scale ring meter color scheme
#define RED2RED 0
#define GREEN2GREEN 1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN 5
// conversion factor degrees to radials
#define DEG2RAD 0.0174532925
time_t t;
int utcOffset = 3 * 60 * 60;
double latitude = 55.7522 ;
double longitude = 37.6156 ;
// data connection and acquisition variables
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// API Openweathermap account
String openWeatherMapApiKey = "09a7aeb9f0441ca1a0607f253e25d670";
String city = "Caino";
// "NL" for The Netherlands
String countryCode = "IT";
// memory allocation json string
String jsonDocument (1024);
// timer internet access for server download
// testing purposes = 30 seconds
unsigned long lastTime = 0;
// is set at 1 seconds in Setup and to 5 minutes in Loop
unsigned long timerDelay;
// joint variables
float temp_01 = 10;
float hum_01;
int hum_02;
// rainbow scale ring meter variables
// time for next update
uint32_t runTime = -99999;
// value to be displayed in circular scale
int reading = 10;
int tesmod = 0;
// these two variables govern the position
int rGaugePos_x = 0;
// of the square + gauge on the display
int rGaugePos_y = 155;
// governs diameter of rainbow gauge
int ringmeterRadius = 65;
// some custom labels
char* ringlabel[] = {"", "*C", "%", "mBar"};
float tempRainbowgauge;
// governs position of numerical output rainbow scale
// small needle meter
int j;
// pivot coordinates needle of small gauge
int pivotNeedle_x = 165;
int pivotNeedle_y = 222;
// center x of edge markers circle left gauge
float center_x1 = 160;
// center y of edge markers circle left gauge
float center_y1 = 228;
// for scale markers
int radius_s = 65;
// gauge needle length
int needleLength = 45;
// edge marker length
int edgemarkerLength = 5;
float edge_x1, edge_y1, edge_x1_out, edge_y1_out;
float angleNeedle = 0;
float needle_x, needle_y;
float needle_x_old, needle_y_old;
float angleCircle = 0;
// pivot coordinates needle of small gauge
int pivot_x = 165;
int pivot_y = 222;
// circle segment 'pie chart' meter variables
byte inc = 0;
unsigned int col = 0;
float pivotHumcircle__x = 198;
float pivotHumcircle__y = 274;
float startAngle = 0;
// subtended angle
float subAngle;
// circle radius
int r = 34;
// compass wind direction pointer
float compassPivot_x = 158;
float compassPivot_y = 65;
float c_x1, c_x2, c_x3, c_x4;
float c_y1, c_y2, c_y3, c_y4;
float c_x1_old, c_x2_old, c_x3_old, c_x4_old;
float c_y1_old, c_y2_old, c_y3_old, c_y4_old;
float windDir_01;
float compassAngle;
int compass_r = 22;
// wind sector labels
char* sector [] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"};
// indicator for wind sector
int h;
void setup() {
moon_prev.setColorDepth(16);
moon_cur.setColorDepth(16);
moon_next.setColorDepth(16);
moon_prev.createSprite(76, 78);
moon_cur.createSprite(76, 78);
moon_cur.createSprite(76, 78);
Serial.begin (9600);
tft.init ();
tft.setRotation(0);
tft.fillScreen (TFT_BLACK);
tft.setTextSize(2);
tft.println ("network ");
tft.println ("connecting");
WiFi.begin (ssid, password);
Serial.println ("connecting");
while (WiFi.status() != WL_CONNECTED) {
delay (500);
Serial.print (".");
tft.print (".");
}
Serial.println ();
Serial.print ("Connected to WiFi network ");
tft.println ("connected to ");
tft.println ();
Serial.print (ssid);
tft.println (ssid);
delay(1000);
tft.fillScreen (TFT_BLACK);
Serial.print (" - IP adress: ");
Serial.println (WiFi.localIP());
Serial.println ("timer set to 30 seconds (timerDelay variable) - it will take 30 seconds before publishing the first reading.");
timeClient.begin();
timeClient.setTimeOffset(3 * 60 * 60);
timeClient.update();
setTime(timeClient.getEpochTime());
t = now();
char timeStr[100];
strftime(timeStr, sizeof(timeStr), "%H:%M", localtime(&t));
spr.setColorDepth(16);
spr.createSprite(tft.width(), 80);
spr.fillSprite(TFT_BLACK);
spr.loadFont(calibri72);
spr.setTextColor (COLOR_CLOCK, BLACK);
//spr.setTextDatum(TR_DATUM);
spr.drawString(timeStr, 50, 0);
spr.pushSprite(0, 0);
/*
spr.fillSprite(TFT_BLACK);
spr.loadFont(zCalibri24);
spr.setTextColor (COLOR_MOON,BLACK);
spr.drawString("луна",80,0);
spr.pushSprite(0,220);
*/
MoonRise mr;
mr.calculate(latitude, longitude, t - utcOffset);
// Returned values:
bool moonVisible = mr.isVisible;
bool moonHasRise = mr.hasRise;
bool moonHasSet = mr.hasSet;
// Where the moon will rise/set in degrees from
float moonRiseAz = mr.riseAz;
// North
float moonSetAz = mr.setAz;
// Additional returned values requiring conversion from UTC to local time zone
// on the Arduino.
time_t moonQueryTime = mr.queryTime + utcOffset;
time_t moonRiseTime = mr.riseTime + utcOffset;
time_t moonSetTime = mr.setTime + utcOffset;
strftime(timeStr, sizeof(timeStr), "%H:%M", localtime(&moonRiseTime));
Serial.println(timeStr);
strftime(timeStr, sizeof(timeStr), "%H:%M", localtime(&moonSetTime));
Serial.println(timeStr);
if ((!mr.hasRise || (mr.hasRise && mr.riseTime > mr.queryTime)) &&
(!mr.hasSet || (mr.hasSet && mr.setTime > mr.queryTime)))
Serial.printf("\tNo moon rise or set during preceding %d hours\n", MR_WINDOW / 2);
if (mr.hasRise && mr.riseTime < mr.queryTime)
Serial.printf("\tMoon rise at %.24s, Azimuth %.2f\n", ctime(&mr.riseTime), mr.riseAz);
if (mr.hasSet && mr.setTime < mr.queryTime)
Serial.printf("\tMoon set at %.24s, Azimuth %.2f\n", ctime(&mr.setTime), mr.setAz);
Serial.printf("Succeeding event:\n");
if ((!mr.hasRise || (mr.hasRise && mr.riseTime < mr.queryTime)) && (!mr.hasSet || (mr.hasSet && mr.setTime < mr.queryTime)))
Serial.printf("\tNo moon rise or set during succeeding %d hours\n", MR_WINDOW / 2);
if (mr.hasRise && mr.riseTime > mr.queryTime)
Serial.printf("\tMoon rise at %.24s, Azimuth %.2f\n", ctime(&mr.riseTime), mr.riseAz);
if (mr.hasSet && mr.setTime > mr.queryTime)
Serial.printf("\tMoon set at %.24s, Azimuth %.2f\n", ctime(&mr.setTime), mr.setAz);
if (mr.isVisible)
Serial.printf("Moon visible.\n");
else
Serial.printf("Moon not visible.\n");
spr.unloadFont();
drawStatic();
drawMoonDay(-1);
drawMoonDay(0);
drawMoonDay(1);
// add wind sector reporter
}
String displayTime(time_t time) {
char timeStr[100];
strftime(timeStr, sizeof(timeStr), "%H:%M", localtime(&time));
return (String) timeStr;
}
void drawMoonDay(int day) {
moon_prev.fillSprite(TFT_BLACK);
moon_prev.loadFont(zCalibri24);
moon_prev.setTextColor (COLOR_MOON, BLACK);
MoonRise mr;
mr.calculate(latitude, longitude, t - utcOffset + 86400 * day);
time_t moonRiseTime = mr.riseTime + utcOffset;
time_t moonSetTime = mr.setTime + utcOffset;
moon_prev.loadFont(zCalibri48);
moon_prev.drawString("26", 10, 0);
moon_prev.unloadFont();
moon_prev.loadFont(zCalibri24);
moon_prev.drawString(displayTime(moonRiseTime), 10, 40);
moon_prev.drawString(displayTime(moonSetTime), 10, 60);
moon_prev.pushSprite(4 + 80 * day + 80, 241);
moon_prev.unloadFont();
}
void drawStatic() {
tft.loadFont(zCalibri24);
tft.setTextColor (COLOR_MOON, BLACK);
tft.drawString(city, 80, 220);
tft.drawRoundRect ( 2, 240, 78, 319, 4, GREEN);
// tft.drawRoundRect ( 82, 240, 158, 319, 4, GREEN);
// tft.drawRoundRect ( 83, 241, 157, 318, 4, GREEN);
tft.drawRoundRect (162, 240, 239, 319, 4, GREEN);
}
void loop() {/*
tft.fillScreen(TFT_DARKGREY);
int xpos = tft.width() / 2; // Half the screen width
int ypos = 50;
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Small font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
spr.loadFont(zCalibri48); // Must load the font first into the sprite class
spr.createSprite(240, 50); // Create a sprite 100 pixels wide and 50 high
spr.fillSprite(TFT_BLUE);
spr.drawRect(0, 0, 100, 50, TFT_WHITE); // Draw sprite border outline (so we see extent)
spr.setTextColor(TFT_YELLOW, TFT_DARKGREY); // Set the sprite font colour and the background colour
spr.setTextDatum(MC_DATUM); // Middle Centre datum
spr.drawString("15pt font", 50, 25 ); // Coords of middle of 100 x 50 Sprite
spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10
spr.pushSprite(10, 70, TFT_BLUE); // Push to TFT screen, TFT_BLUE is transparent
spr.unloadFont(); // Remove the font from sprite class to recover memory used
delay(4000);
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Large font
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
tft.fillScreen(TFT_BLACK);
// Beware: Sprites are a different "class" to TFT, so different fonts can be loaded
// in the tft and sprite instances, so load the font in the class instance you use!
// In this example this means the spr. instance.
spr.loadFont(zCalibri48); // Load another different font into the sprite instance
// 100 x 50 sprite was created above and still exists...
spr.fillSprite(TFT_GREEN);
spr.setTextColor(TFT_BLACK, TFT_GREEN); // Set the font colour and the background colour
spr.setTextDatum(MC_DATUM); // Middle Centre datum
spr.drawString("Fits", 50, 25); // Make sure text fits in the Sprite!
spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10
spr.fillSprite(TFT_RED);
spr.setTextColor(TFT_WHITE, TFT_RED); // Set the font colour and the background colour
spr.drawString("Too big", 50, 25); // Text is too big to all fit in the Sprite!
spr.pushSprite(10, 70); // Push to TFT screen coord 10, 70
// Draw changing numbers - no flicker using this plot method!
// >>>> Note: it is best to use drawNumber() and drawFloat() for numeric values <<<<
// >>>> this reduces digit position movement when the value changes <<<<
// >>>> drawNumber() and drawFloat() functions behave like drawString() and are <<<<
// >>>> supported by setTextDatum() and setTextPadding() <<<<
spr.setTextDatum(TC_DATUM); // Top Centre datum
spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour
for (int i = 0; i <= 200; i++) {
spr.fillSprite(TFT_BLUE);
spr.drawFloat(i / 100.0, 2, 50, 10); // draw with 2 decimal places at 50,10 in sprite
spr.pushSprite(10, 130); // Push to TFT screen coord 10, 130
delay (20);
}
spr.unloadFont(); // Remove the font to recover memory used
spr.deleteSprite(); // Recover memory
delay(1000);
// doTheHardWork ();
*/}