@red_car
For some reason instead of displaying every second on my screen, now that I've added moon phases, my clock displays every second or third second. What did I do wrong now????
https://forum.arduino.cc/t/ds1302-not-displaying-seconds/1007353/7
#include <OneWire.h>
#include <DallasTemperature.h>
#include <virtuabotixRTC.h> //Libraries needed
#include "Adafruit_GFX.h" // Hardware-specific library
#include <MCUFRIEND_kbv.h>
#include <SPI.h>
#include <SD.h>
MCUFRIEND_kbv tft;
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 1000
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
#define BLACK 0x0000
#define LIGHTGREY 0xC618
#define WHITE 0xFFFF
#define RED 0xF800
String nfm = ""; // days to next full moon
#include "Full.c"
#include "Draining.c"
#include "Drained.c"
#include "Empty.c"
#include "Charging.c"
#define SD_CS 48
#define NAMEMATCH "" // "" matches any name
//#define NAMEMATCH "tiger" // *tiger*.bmp
//#define PALETTEDEPTH 0 // do not support Palette modes
#define PALETTEDEPTH 8 // support 256-colour Palette
char namebuf[32] = "/"; //BMP files in root directory
//char namebuf[32] = "/bitmaps/"; //BMP directory e.g. files in /bitmaps/*.bmp
File root;
int pathlen;
virtuabotixRTC myRTC(6, 7, 8);
uint8_t prevDay, prevMonth, prevSec, prevMin, prevHour, prevVolt, prevTemp, prevMoon;
uint16_t prevYear;
void setup() {
Serial.begin(9600);
sensors.begin();
tft.reset();
tft.begin(0x9488);
tft.setRotation(1);
myRTC.setDS1302Time(00, 54, 17, 04, 30, 06, 2022);
tft.fillScreen(BLACK);
tft.setTextSize(3);
sensors.requestTemperatures();
tft.drawLine(0, 27, 480, 27, LIGHTGREY);
tft.drawLine(0, 28, 480, 28, LIGHTGREY);
tft.drawLine(240, 0, 240, 28, LIGHTGREY);
tft.drawLine(241, 0, 241, 28, LIGHTGREY);
tft.drawLine(0, 288, 480, 288, LIGHTGREY);
tft.drawLine(0, 289, 480, 289, LIGHTGREY);
tft.drawLine(240, 288, 240, 320, LIGHTGREY);
tft.drawLine(241, 289, 241, 320, LIGHTGREY);
bool good = SD.begin(SD_CS);
if (!good) {
Serial.print(F("cannot start SD"));
while (1);
}
}
void loop() {
myRTC.updateTime();
sensors.requestTemperatures();
if (myRTC.dayofmonth != prevDay)
{
prevDay = myRTC.dayofmonth;
tft.setCursor(5, 3);
tft.fillRect(5, 3, 33, 21, BLACK);
if (myRTC.dayofmonth < 10)
{
tft.print("0");
tft.print(myRTC.dayofmonth);
}
else
{
tft.print(myRTC.dayofmonth);
}
}
tft.setCursor(41, 3);
tft.print("/");
if (myRTC.month != prevMonth)
{
prevMonth = myRTC.month;
tft.setCursor(59, 3);
tft.fillRect(59, 3, 33, 21, BLACK);
if (myRTC.month < 10) {
tft.print("0");
tft.print(myRTC.month);
}
else {
tft.print(myRTC.month);
}
}
tft.setCursor(95, 3);
tft.print("/");
if (myRTC.year != prevYear)
{
prevYear = myRTC.year;
tft.setCursor(113, 3);
tft.fillRect(113, 3, 70, 21, BLACK);
tft.print(myRTC.year);
}
if (myRTC.hours != prevHour)
{
prevHour = myRTC.hours;
tft.setCursor(246, 3);
tft.fillRect(246, 3, 33, 21, BLACK);
if (myRTC.hours < 10) {
tft.print("0");
tft.print(myRTC.hours);
}
else {
tft.print(myRTC.hours);
}
}
tft.setCursor(279, 3);
tft.print(":");
if (myRTC.minutes != prevMin)
{
prevMin = myRTC.minutes;
tft.setCursor(295, 3);
tft.fillRect(295, 3, 33, 21, BLACK);
if (myRTC.minutes < 10) {
tft.print("0");
tft.print(myRTC.minutes);
}
else {
tft.print(myRTC.minutes);
}
}
tft.setCursor(329, 3);
tft.print(":");
if (myRTC.seconds != prevSec)
{
prevSec = myRTC.seconds;
tft.setCursor(345, 3);
tft.fillRect(345, 3, 33, 21, BLACK);
if (myRTC.seconds < 10) {
tft.print("0");
tft.print(myRTC.seconds);
}
else {
tft.print(myRTC.seconds);
}
}
int sensor = analogRead(A1);
float voltage = (sensor * 5.0) / 1023;
tft.setTextSize(3);
if (voltage != prevVolt)
{
prevVolt = voltage;
//tft.fillRect(3, 33, 70, 21, BLACK);
//tft.setCursor(3, 33);
Serial.println(voltage);
battery();
}
if (sensors.getTempCByIndex(0) != prevTemp)
{
prevTemp = sensors.getTempCByIndex(0);
tft.setCursor(5, 294);
tft.fillRect(5, 294, 90, 21, BLACK);
tft.print(sensors.getTempCByIndex(0));
}
if (moonPhase != prevMoon)
{
prevMoon = moonPhase;
moonPhase();
}
}
double julianDate(int y, int m, int d) {
// convert a date to a Julian Date}
int mm, yy;
double k1, k2, k3;
double j;
yy = y - int((12 - m) / 10);
mm = m + 9;
if (mm >= 12) {
mm = mm - 12;
}
k1 = 365.25 * (yy + 4172);
k2 = int((30.6001 * mm) + 0.5);
k3 = int((((yy / 100) + 4) * 0.75) - 38);
j = k1 + k2 + d + 59;
j = j - k3; // j is the Julian date at 12h UT (Universal Time)
return j;
}
int moon_phase() {
// calculates the age of the moon phase(0 to 7)
// there are eight stages, 0 is full moon and 4 is a new moon
// DateTime now = RTC.now();
double jd = 0; // Julian Date
double ed = 0; //days elapsed since start of full moon
int b = 0;
jd = julianDate(myRTC.year, myRTC.month, myRTC.dayofmonth);
//jd = julianDate(1972,1,1); // used to debug this is a new moon
jd = int(jd - 2244116.75); // start at Jan 1 1972
jd /= 29.53; // divide by the moon cycle
b = jd;
jd -= b; // leaves the fractional part of jd
ed = jd * 29.53; // days elapsed this month
nfm = String((int(29.53 - ed))); // days to next full moon
b = jd * 8 + 0.5;
b = b & 7;
return b;
}
uint8_t ret;
void moonPhase() {
int mp = moon_phase();
Serial.print("Returned Moon Phase :"); Serial.println(mp);
switch (mp) {
case 0:
ret = showBMP("/01.bmp", 3, 33);
Serial.println("Printing full moon phase");
break;
case 1:
ret = showBMP("/02.bmp", 3, 33);
Serial.println("Printing Waning Gibbous phase");
break;
case 2:
ret = showBMP("/03.bmp", 3, 33);
Serial.println("Printing Third Quarter phase");
break;
case 3:
ret = showBMP("/04.bmp", 3, 33);
Serial.println("Printing Waning Crescent phase");
break;
case 4:
ret = showBMP("/05.bmp", 3, 33);
Serial.println("Printing new moon phase");
break;
case 5:
ret = showBMP("/06.bmp", 3, 33);
Serial.println("Printing Waxing Crescent phase");
break;
case 6:
ret = showBMP("/07.bmp", 3, 33);
Serial.println("Printing First Quarter phase");
break;
case 7:
ret = showBMP("/08.bmp", 3, 33);
Serial.println("Printing Waxing Gibbous phase");
break;
}
const char* newNfm = (const char*) nfm.c_str();
}
void battery () {
int sensor = analogRead(A1);
Serial.println(sensor);
float voltage = (sensor * 5.0) / 1023;
Serial.println(voltage);
if (voltage > 3.00) {
tft.drawRGBBitmap(435, 3, Charging, 36, 21);
}
if ((voltage <= 3.00) && (voltage > 2.35)) {
tft.drawRGBBitmap(435, 3, Full, 36, 21);
}
if ((voltage <= 2.35) && (voltage > 1.70)) {
tft.drawRGBBitmap(435, 3, Draining, 36, 21);
}
if ((voltage <= 1.70) && (voltage > 1.00)) {
tft.drawRGBBitmap(435, 3, Drained, 36, 21);
}
if (voltage <= 1.00) {
tft.drawRGBBitmap(435, 3, Empty, 36, 21);
}
}
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL 20
uint16_t read16(File& f) {
uint16_t result; // read little-endian
f.read((uint8_t*)&result, sizeof(result));
return result;
}
uint32_t read32(File& f) {
uint32_t result;
f.read((uint8_t*)&result, sizeof(result));
return result;
}
uint8_t showBMP(char *nm, int x, int y)
{
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24, 16, 8, 4, 1)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
uint8_t bitmask, bitshift;
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
uint32_t pos; // seek position
boolean is565 = false; //
uint16_t bmpID;
uint16_t n; // blocks read
uint8_t ret;
if ((x >= tft.width()) || (y >= tft.height()))
return 1; // off screen
bmpFile = SD.open(nm); // Parse BMP header
bmpID = read16(bmpFile); // BMP signature
(void) read32(bmpFile); // Read & ignore file size
(void) read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
(void) read32(bmpFile); // Read & ignore DIB header size
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
n = read16(bmpFile); // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
pos = read32(bmpFile); // format
if (bmpID != 0x4D42) ret = 2; // bad ID
else if (n != 1) ret = 3; // too many planes
else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
else {
bool first = true;
is565 = (pos == 3); // ?already in 16-bit format
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
if (bmpHeight < 0) { // If negative, image is in top-down order.
bmpHeight = -bmpHeight;
flip = false;
}
w = bmpWidth;
h = bmpHeight;
if ((x + w) >= tft.width()) // Crop area to be loaded
w = tft.width() - x;
if ((y + h) >= tft.height()) //
h = tft.height() - y;
if (bmpDepth <= PALETTEDEPTH) { // these modes have separate palette
//bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
bmpFile.seek(bmpImageoffset - (4 << bmpDepth)); //54 for regular, diff for colorsimportant
bitmask = 0xFF;
if (bmpDepth < 8)
bitmask >>= bmpDepth;
bitshift = 8 - bmpDepth;
n = 1 << bmpDepth;
lcdbufsiz -= n;
palette = lcdbuffer + lcdbufsiz;
for (col = 0; col < n; col++) {
pos = read32(bmpFile); //map palette to 5-6-5
palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
}
}
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
uint8_t r, g, b, *sdptr;
int lcdidx, lcdleft;
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; ) { //pixels in row
lcdleft = w - col;
if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
uint16_t color;
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
r = 0;
}
switch (bmpDepth) { // Convert pixel from BMP to TFT format
case 24:
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
color = tft.color565(r, g, b);
break;
case 16:
b = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
if (is565)
color = (r << 8) | (b);
else
color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
break;
case 1:
case 4:
case 8:
if (r == 0)
b = sdbuffer[buffidx++], r = 8;
color = palette[(b >> bitshift) & bitmask];
r -= bmpDepth;
b <<= bmpDepth;
break;
}
lcdbuffer[lcdidx] = color;
}
tft.pushColors(lcdbuffer, lcdidx, first);
first = false;
col += lcdidx;
} // end cols
} // end rows
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
ret = 0; // good render
}
bmpFile.close();
return (ret);
}