Moon Phases are displaying incorrectly

@runaway_pancake

Me neither . I'm following post #32, not sure why it needs to be done that way, I'm just trying it out to see if it does actually work better.

I'm sorry, you'll have to ask @ec2021 these questions, as I've never heard of a better replacement for a switch case statement...

The code suggested by @ec2021 might be not correct as it may not return true or false in all cases.
Unless the showBMP actually returns true or false.

Also he suggests that to be a function. A function definition needs to be outside loop, setup or any other function.

The function should be called from your code. Like this:
moonPhase(moon_phase());

I would rename the function to:
showMoonPhase()
As that would explain better what the function does.

1 Like

I used the same function names as the TO. That's the reason for the two similar names (which I do not like, but they are as they have been ...)

As the parameter mp is an integer it could well be out of the scope, less zero or larger than 7. In that case nothing happens and the function returns false.

If the value is in the range it creates the appropriate filename and returns the result of ShowBMP() which is true if successful or false if not....

The reason for the problems is the wrong application of the function...

  • Take the sketch from post 31
  • Delete the complete function "void moonPhase()“
  • Copy the code from post 32
  • Paste it to the place where you deleted the function "void moonPhase()"
  • Change in loop() the call "moonPhase();" to "moonPhase(moon_phase());"

Now the sketch should compile and work. It will not use the return value, as this requires additional changes to the code.

The TO might also post the full sketch and I will be happy to insert the changes.

I have tested the general function of the snippet. It works...

That is precisely what I did.

The complete sketch:

unsigned long previousMillis = 0;
const long interval = 1;

#include "Full.c"
#include "Draining.c"
#include "Drained.c"
#include "Empty.c"
#include "Charging.c"

#include "nonBlockingDS18B20.h"

enum machineStates {
  IDLE, WAITING_FOR_CONVERSION, ABORTED
};

const uint8_t ONE_WIRE_BUS = 2; // Change this to Pin # connected to OneWire bus
const uint8_t RESOLUTION = 12;
const unsigned long maxWaitTime = 5000;
const unsigned long interMeasurementPeriod = 1000;
machineStates currentState;
unsigned long measurementStartTime, measurementStopTime;
unsigned long interMeasurementTimer;

OneWire oneWire(ONE_WIRE_BUS);
nonBlockingDS18B20 tempSensors(&oneWire);

void printAddress(DeviceAddress);

uint8_t numDS18;

#define USE_TOUCH    0x2046

#include <virtuabotixRTC.h> //Libraries needed

virtuabotixRTC myRTC(6, 7, 8);

#include "Adafruit_GFX.h"    // Hardware-specific library
#include <MCUFRIEND_kbv.h>
#include <SPI.h>
#include <SD.h>
MCUFRIEND_kbv tft;       //
#define TFT_BEGIN()    tft.begin(0x9488)

#include <XPT2046_Touchscreen.h>           // Hardware SPI library
char *name = "Shield XPT2046 Calibration";  //edit name of shield
const int TS_LANDSCAPE = 1; //XPT2046_TouchScreen.h
const int TS_LEFT = 261, TS_RT = 3770, TS_TOP = 3869, TS_BOT = 296;
#define XPT_CS  53      // MEGA2560 SHIELD 
#define XPT_IRQ 255     // XPT2046 library does not like IRQ
XPT2046_Touchscreen ts(XPT_CS, XPT_IRQ);

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
  bool pressed = ts.touched();
  if (pressed) {
    TS_Point p = ts.getPoint();
    if (TS_LANDSCAPE) mapxy(p.y, p.x);
    else mapxy(p.x, p.y);
  }
  return pressed;
}

void Touch_init(void)
{
  ts.begin();
}

void mapxy(int x, int y)                //maps ADC to pixel_x, pixel_y
{
  int aspect = tft.getRotation();     //LANDSCAPE
  int tft_width = tft.width();
  int tft_height = tft.height();
  switch (aspect & 3) {
    case 0:      //PORTRAIT
      pixel_x = map(x, TS_LEFT, TS_RT, 0, tft_width);
      pixel_y = map(y, TS_TOP, TS_BOT, 0, tft_height);
      break;
    case 1:      //LANDSCAPE
      pixel_x = map(y, TS_TOP, TS_BOT, 0, tft_width);
      pixel_y = map(x, TS_RT, TS_LEFT, 0, tft_height);
      break;
    case 2:      //PORTRAIT REV
      pixel_x = map(x, TS_RT, TS_LEFT, 0, tft_width);
      pixel_y = map(y, TS_BOT, TS_TOP, 0, tft_height);
      break;
    case 3:      //LANDSCAPE REV
      pixel_x = map(y, TS_BOT, TS_TOP, 0, tft_width);
      pixel_y = map(x, TS_LEFT, TS_RT, 0, tft_height);
      break;
  }
}

Adafruit_GFX_Button temp_btn, humidity_btn, home_btn, more_btn;

#define BLACK 0x0000       /*   0,   0,   0 */
#define NAVY 0x000F        /*   0,   0, 128 */
#define DARKGREEN 0x03E0   /*   0, 128,   0 */
#define DARKCYAN 0x03EF    /*   0, 128, 128 */
#define MAROON 0x7800      /* 128,   0,   0 */
#define PURPLE 0x780F      /* 128,   0, 128 */
#define OLIVE 0x7BE0       /* 128, 128,   0 */
#define LIGHTGREY 0xC618   /* 192, 192, 192 */
#define DARKGREY 0x7BEF    /* 128, 128, 128 */
#define BLUE 0x001F        /*   0,   0, 255 */
#define GREEN 0x07E0       /*   0, 255,   0 */
#define CYAN 0x07FF        /*   0, 255, 255 */
#define RED 0xF800         /* 255,   0,   0 */
#define MAGENTA 0xF81F     /* 255,   0, 255 */
#define YELLOW 0xFFE0      /* 255, 255,   0 */
#define WHITE 0xFFFF       /* 255, 255, 255 */
#define ORANGE 0xFD20      /* 255, 165,   0 */
#define GREENYELLOW 0xAFE5 /* 173, 255,  47 */
#define PINK 0xF81F

uint8_t displayScreenNo, prevDay, prevMonth, prevSec, prevMin, prevHour, prevVolt, prevMoon;
uint16_t prevYear;

uint8_t index;
static float prevTemp = 999.99 ; // an unlikely value
float currentTempF = tempSensors.getLatestTempC(index);

String nfm = "";

#define SD_CS     48

#define NAMEMATCH ""
#define PALETTEDEPTH   8     // support 256-colour Palette

char namebuf[32] = "/";

File root;
int pathlen;

void setup() {
  //myRTC.setDS1302Time(00, 07, 18, 07, 9, 07, 2022);
  Serial.begin(2000000);
  numDS18 = tempSensors.begin(RESOLUTION);
  if (numDS18 == 0) {
    Serial.println(
      F("Did not locate any DS-type Temperature Sensors, aborting"));
    while (1) {
      delay(0);
    }
  }
  TFT_BEGIN();
  bool good = SD.begin(SD_CS);
  if (!good) {
    Serial.print(F("cannot start SD"));
    while (1);
  }
  Touch_init();
  tft.setRotation(1);            //PORTRAIT
  tft.fillScreen(BLACK);
  home_btn.initButton(&tft,  440, 280, 80, 80, LIGHTGREY, CYAN, BLACK, "HOME", 2);
  home_btn.drawButton(false);
  more_btn.initButton(&tft,  440, 40, 80, 80, LIGHTGREY, CYAN, BLACK, "MORE", 2);
  more_btn.drawButton(false);
  temp_btn.initButton(&tft,  440, 120, 80, 80, LIGHTGREY, CYAN, BLACK, "TEMP", 2);
  humidity_btn.initButton(&tft, 440, 200, 80, 80, LIGHTGREY, CYAN, BLACK, "%", 2);
  temp_btn.drawButton(false);
  humidity_btn.drawButton(false);
  tft.setTextSize(3);
}

void loop() {
  unsigned int IntensityOfLight;

  IntensityOfLight = analogRead(A0);

  myRTC.updateTime();

  bool down = Touch_getXY();
  home_btn.press(down && home_btn.contains(pixel_x, pixel_y));
  more_btn.press(down && more_btn.contains(pixel_x, pixel_y));
  temp_btn.press(down && temp_btn.contains(pixel_x, pixel_y));
  humidity_btn.press(down && humidity_btn.contains(pixel_x, pixel_y));
  if (home_btn.justReleased()) {
    home_btn.drawButton(true);
    more_btn.drawButton();
    temp_btn.drawButton();
    humidity_btn.drawButton();
  }
  if (more_btn.justReleased()) {
    more_btn.drawButton(true);
    home_btn.drawButton();
    temp_btn.drawButton();
    humidity_btn.drawButton();
  }
  if (temp_btn.justReleased()) {
    home_btn.drawButton();
    temp_btn.drawButton(true);
    more_btn.drawButton();
    humidity_btn.drawButton();
  }
  if (humidity_btn.justReleased()) {
    home_btn.drawButton();
    temp_btn.drawButton();
    humidity_btn.drawButton(true);
    more_btn.drawButton();
  }
  if (home_btn.justPressed())
  {
    tft.fillScreen(BLACK);
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    drawHomeScreen();
    displayScreenNo = 1;
    home_btn.drawButton(true);
    temp_btn.drawButton(false);
    humidity_btn.drawButton(false);
    more_btn.drawButton(false);
  }
  if (more_btn.justPressed())
  {
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    tft.fillScreen(BLACK);
    drawMoreScreen();
    displayScreenNo = 2;
    more_btn.drawButton(true);
    temp_btn.drawButton(false);
    humidity_btn.drawButton(false);
    home_btn.drawButton(false);
  }
  if (temp_btn.justPressed())
  {
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    tft.fillScreen(BLACK);
    drawDetailScreenTemp();
    displayScreenNo = 3;
    temp_btn.drawButton(true);
    home_btn.drawButton(false);
    humidity_btn.drawButton(false);
    more_btn.drawButton(false);
  }
  if (humidity_btn.justPressed())
  {
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    tft.fillScreen(BLACK);
    drawDetailScreenHumidity();
    displayScreenNo = 4;
    humidity_btn.drawButton(true);
    temp_btn.drawButton(false);
    home_btn.drawButton(false);
    more_btn.drawButton(false);
  }
  switch (displayScreenNo)
  {
    case 1: drawDynHomeScreen(); break;
    case 2: drawDynMoreScreen(); break;
    case 3: drawDynDetailScreenTemp(); break;
    case 4: drawDynDetailScreenHumidity(); break;
  }
}

void drawHomeScreen() {
  tft.drawLine(0, 27, 480, 27, LIGHTGREY);
  tft.drawLine(0, 28, 480, 28, LIGHTGREY);
  tft.drawLine(200, 0, 200, 28, LIGHTGREY);
  tft.drawLine(201, 0, 201, 28, LIGHTGREY);

  tft.drawLine(0, 288, 480, 288, LIGHTGREY);
  tft.drawLine(0, 289, 480, 289, LIGHTGREY);
  tft.drawLine(200, 288, 200, 320, LIGHTGREY);
  tft.drawLine(201, 289, 201, 320, LIGHTGREY);
}

void drawDetailScreenHumidity() {

  tft.drawLine(0, 27, 480, 27, LIGHTGREY);
  tft.drawLine(0, 28, 480, 28, LIGHTGREY);
  tft.drawLine(200, 0, 200, 28, LIGHTGREY);
  tft.drawLine(201, 0, 201, 28, LIGHTGREY);


  tft.drawLine(27, 33, 339, 33, LIGHTGREY);
  tft.drawLine(27, 59, 339, 59, LIGHTGREY);
  tft.drawLine(27, 85, 339, 85, LIGHTGREY);
  tft.drawLine(27, 111, 339, 111, LIGHTGREY);
  tft.drawLine(27, 137, 339, 137, LIGHTGREY);
  tft.drawLine(27, 163, 339, 163, LIGHTGREY);
  tft.drawLine(27, 189, 339, 189, LIGHTGREY);
  tft.drawLine(27, 215, 339, 215, LIGHTGREY);
  tft.drawLine(27, 241, 339, 241, LIGHTGREY);
  tft.drawLine(27, 267, 339, 267, LIGHTGREY);
  tft.drawLine(27, 293, 339, 293, LIGHTGREY);

  tft.drawLine(339, 33, 339, 293, LIGHTGREY);
  tft.drawLine(313, 33, 313, 293, LIGHTGREY);
  tft.drawLine(287, 33, 287, 293, LIGHTGREY);
  tft.drawLine(261, 33, 261, 293, LIGHTGREY);
  tft.drawLine(236, 33, 236, 293, LIGHTGREY);
  tft.drawLine(209, 33, 209, 293, LIGHTGREY);
  tft.drawLine(183, 33, 183, 293, LIGHTGREY);
  tft.drawLine(157, 33, 157, 293, LIGHTGREY);
  tft.drawLine(131, 33, 131, 293, LIGHTGREY);
  tft.drawLine(105, 33, 105, 293, LIGHTGREY);
  tft.drawLine(79, 33, 79, 293, LIGHTGREY);
  tft.drawLine(53, 33, 53, 293, LIGHTGREY);
  tft.drawLine(27, 33, 27, 293, LIGHTGREY);

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(2, 33);
  tft.print("100%");
  tft.setCursor(6, 59);
  tft.print("90%");
  tft.setCursor(6, 85);
  tft.print("80%");
  tft.setCursor(6, 111);
  tft.print("70%");
  tft.setCursor(6, 137);
  tft.print("60%");
  tft.setCursor(6, 163);
  tft.print("50%");
  tft.setCursor(6, 189);
  tft.print("40%");
  tft.setCursor(6, 215);
  tft.print("30%");
  tft.setCursor(6, 241);
  tft.print("20%");
  tft.setCursor(6, 267);
  tft.print("10%");
  tft.setCursor(6, 293);
  tft.print("0%");

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(26, 300);
  tft.print("6");
  tft.setCursor(44, 300);
  tft.print("5.5");
  tft.setCursor(77, 300);
  tft.print("5");
  tft.setCursor(96, 300);
  tft.print("4.5");
  tft.setCursor(128, 300);
  tft.print("4");
  tft.setCursor(148, 300);
  tft.print("3.5");
  tft.setCursor(181, 300);
  tft.print("3");
  tft.setCursor(200, 300);
  tft.print("2.5");
  tft.setCursor(234, 300);
  tft.print("2");
  tft.setCursor(253, 300);
  tft.print("1.5");
  tft.setCursor(285, 300);
  tft.print("1");
  tft.setCursor(305, 300);
  tft.print("0.5");
  tft.setCursor(337, 300);
  tft.print("0");
}

void drawMoreScreen() {
  more_btn.drawButton(true);
}

void drawDetailScreenTemp() {

  tft.drawLine(0, 27, 480, 27, LIGHTGREY);
  tft.drawLine(0, 28, 480, 28, LIGHTGREY);
  tft.drawLine(200, 0, 200, 28, LIGHTGREY);
  tft.drawLine(201, 0, 201, 28, LIGHTGREY);

  tft.drawLine(27, 33, 339, 33, LIGHTGREY);
  tft.drawLine(27, 59, 339, 59, LIGHTGREY);
  tft.drawLine(27, 85, 339, 85, LIGHTGREY);
  tft.drawLine(27, 111, 339, 111, LIGHTGREY);
  tft.drawLine(27, 137, 339, 137, LIGHTGREY);
  tft.drawLine(27, 163, 339, 163, LIGHTGREY);
  tft.drawLine(27, 189, 339, 189, LIGHTGREY);
  tft.drawLine(27, 215, 339, 215, LIGHTGREY);
  tft.drawLine(27, 241, 339, 241, LIGHTGREY);
  tft.drawLine(27, 267, 339, 267, LIGHTGREY);
  tft.drawLine(27, 293, 339, 293, LIGHTGREY);

  tft.drawLine(339, 33, 339, 293, LIGHTGREY);
  tft.drawLine(313, 33, 313, 293, LIGHTGREY);
  tft.drawLine(287, 33, 287, 293, LIGHTGREY);
  tft.drawLine(261, 33, 261, 293, LIGHTGREY);
  tft.drawLine(236, 33, 236, 293, LIGHTGREY);
  tft.drawLine(209, 33, 209, 293, LIGHTGREY);
  tft.drawLine(183, 33, 183, 293, LIGHTGREY);
  tft.drawLine(157, 33, 157, 293, LIGHTGREY);
  tft.drawLine(131, 33, 131, 293, LIGHTGREY);
  tft.drawLine(105, 33, 105, 293, LIGHTGREY);
  tft.drawLine(79, 33, 79, 293, LIGHTGREY);
  tft.drawLine(53, 33, 53, 293, LIGHTGREY);
  tft.drawLine(27, 33, 27, 293, LIGHTGREY);

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(6, 33);
  tft.print("45");
  tft.print((char)247);
  tft.setCursor(6, 59);
  tft.print("40");
  tft.print((char)247);
  tft.setCursor(6, 85);
  tft.print("35");
  tft.print((char)247);
  tft.setCursor(6, 111);
  tft.print("30");
  tft.print((char)247);
  tft.setCursor(6, 137);
  tft.print("25");
  tft.print((char)247);
  tft.setCursor(6, 163);
  tft.print("20");
  tft.print((char)247);
  tft.setCursor(6, 189);
  tft.print("15");
  tft.print((char)247);
  tft.setCursor(6, 215);
  tft.print("10");
  tft.print((char)247);
  tft.setCursor(6, 241);
  tft.print(" 5");
  tft.print((char)247);
  tft.setCursor(6, 267);
  tft.print(" 0");
  tft.print((char)247);
  tft.setCursor(6, 285);
  tft.print("-5");
  tft.print((char)247);

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(26, 300);
  tft.print("6");
  tft.setCursor(44, 300);
  tft.print("5.5");
  tft.setCursor(77, 300);
  tft.print("5");
  tft.setCursor(96, 300);
  tft.print("4.5");
  tft.setCursor(128, 300);
  tft.print("4");
  tft.setCursor(148, 300);
  tft.print("3.5");
  tft.setCursor(181, 300);
  tft.print("3");
  tft.setCursor(200, 300);
  tft.print("2.5");
  tft.setCursor(234, 300);
  tft.print("2");
  tft.setCursor(253, 300);
  tft.print("1.5");
  tft.setCursor(285, 300);
  tft.print("1");
  tft.setCursor(305, 300);
  tft.print("0.5");
  tft.setCursor(337, 300);
  tft.print("0");
}

void battery () {
  int sensor = analogRead(A1);
  //Serial.println(sensor);
  float voltage = (sensor * 5.0) / 1023;
  //Serial.println(voltage);
  if (voltage > 3.65) {
    tft.drawRGBBitmap(355, 3, Charging, 36, 21);
  }
  if ((voltage <= 3.60) && (voltage > 3.20)) {
    tft.drawRGBBitmap(355, 3, Full, 36, 21);
  }
  if ((voltage <= 3.20) && (voltage > 2.80)) {
    tft.drawRGBBitmap(355, 3, Draining, 36, 21);
  }
  if ((voltage <= 2.80) && (voltage > 2.40)) {
    tft.drawRGBBitmap(355, 3, Drained, 36, 21);
  }
  if (voltage <= 2) {
    tft.drawRGBBitmap(355, 3, Empty, 36, 21);
  }
}

void buttons () {
  home_btn.drawButton(false);
  more_btn.drawButton(false);
  temp_btn.drawButton(false);
  humidity_btn.drawButton(false);
}
void drawDynHomeScreen() {
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  if (myRTC.dayofmonth != prevDay)
  {
    prevDay = myRTC.dayofmonth;
    tft.fillRect(5, 3, 33, 21, BLACK);
    tft.setCursor(5, 3);
    if (myRTC.dayofmonth < 10)
    {
      moonPhase();
      tft.print("0");
      tft.print(myRTC.dayofmonth);
    }
    else
    {
      moonPhase();
      tft.print(myRTC.dayofmonth);
    }
  }
  tft.setCursor(41, 3);
  tft.print("/");
  if (myRTC.month != prevMonth)
  {
    prevMonth = myRTC.month;
    tft.fillRect(59, 3, 33, 21, BLACK);
    tft.setCursor(59, 3);
    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.fillRect(113, 3, 70, 21, BLACK);
    tft.setCursor(113, 3);
    tft.print(myRTC.year);
  }
  if (myRTC.hours != prevHour)
  {
    prevHour = myRTC.hours;
    tft.fillRect(206, 3, 33, 21, BLACK);
    tft.setCursor(206, 3);
    if (myRTC.hours < 10) {
      tft.print("0");
      tft.print(myRTC.hours);
    }
    else {
      tft.print(myRTC.hours);
    }
  }
  tft.setCursor(239, 3);
  tft.print(":");
  if (myRTC.minutes != prevMin)
  {
    prevMin = myRTC.minutes;
    tft.fillRect(256, 3, 33, 21, BLACK);
    tft.setCursor(256, 3);
    if (myRTC.minutes < 10) {
      tft.print("0");
      tft.print(myRTC.minutes);
    }
    else {
      tft.print(myRTC.minutes);
    }
  }
  tft.setCursor(290, 3);
  tft.print(":");
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (myRTC.seconds != prevSec)
    {
      prevSec = myRTC.seconds;
      tft.fillRect(306, 3, 33, 21, BLACK);
      tft.setCursor(306, 3);
      if (myRTC.seconds < 10) {
        tft.print("0");
        tft.print(myRTC.seconds);
        Serial.print("0");
        Serial.println(myRTC.seconds);
      }
      else {
        tft.print(myRTC.seconds);
        Serial.println(myRTC.seconds);
      }
    }
  }
  int sensor = analogRead(A1);
  float voltage = (sensor * 5.0) / 1023;
  if (voltage != prevVolt)
  {
    prevVolt = voltage;
    battery();
  }
  uint8_t index;
  static uint32_t loopCount = 0;

  currentMillis = millis();
  switch (currentState) {
    case WAITING_FOR_CONVERSION:
      if (tempSensors.isConversionDone()) {
        // Measurement has finished print results
        measurementStopTime = currentMillis;
        Serial.print(F(" Sensors Took: "));
        Serial.print(measurementStopTime - measurementStartTime);
        Serial.println(F(" ms"));
        Serial.print(loopCount);
        Serial.println(F(" Iterations of loop occurred during this period."));
        // Print measurements from all temperature sensors
        for (index = 0; index < numDS18; index++) {
          Serial.print(F(" Results:  "));
          Serial.print(tempSensors.getLatestTempC(index), 2);
          Serial.println(F(" (C)"));
          if (currentTempF != prevTemp)
          {
            Serial.print(F("Temp values  "));
            Serial.print(prevTemp);
            Serial.print(F("  "));
            Serial.print(currentTempF);
            Serial.print(F("  "));
            prevTemp = tempSensors.getLatestTempC(index);
            Serial.println(prevTemp);
            tft.setCursor(5, 294);
            tft.fillRect(5, 294, 190, 21, BLACK);
            tft.print(tempSensors.getLatestTempC(index), 2);
            tft.print(" ");
            tft.print((char)247);
            tft.print("C");
          }
        }
        // Hang out until time for next measurement
        currentState = IDLE;
        interMeasurementTimer = currentMillis;
      } else if (currentMillis - measurementStartTime >= maxWaitTime) {
        Serial.println(F("Timed Out Waiting for Measurements to Complete -- Aborting"));
        currentState = ABORTED;
      }
      break;

    case IDLE:
      // Check if it's time to start another measurement
      if (currentMillis - interMeasurementTimer >= interMeasurementPeriod) {
        currentState = WAITING_FOR_CONVERSION;
        loopCount = 0;
        // Kick off another set of non-blocking sensor readings
        measurementStartTime = currentMillis;
        if (!tempSensors.startConvertion()) {
          Serial.println(F("Failed to Start Conversion Cycle, Aborting"));
          currentState = ABORTED;
        }
      }
      break;

    case ABORTED:
      break;
  }
  loopCount++;
}

void drawDynDetailScreenHumidity() {
  myRTC.updateTime();
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(5, 3);
  if (myRTC.dayofmonth < 10)
  {
    tft.print("0");
    tft.print(myRTC.dayofmonth);
  }
  else
  {
    tft.print(myRTC.dayofmonth);
  }
  tft.print("/");
  if (myRTC.month < 10) {
    tft.print("0");
    tft.print(myRTC.month);
  }
  else {
    tft.print(myRTC.month);
  }
  tft.print("/");
  tft.print(myRTC.year);
  tft.setCursor(206, 3);
  if (myRTC.hours < 10) {
    tft.print("0");
    tft.print(myRTC.hours);
  }
  else {
    tft.print(myRTC.hours);
  }
  tft.print(":");
  if (myRTC.minutes < 10) {
    tft.print("0");
    tft.print(myRTC.minutes);
  }
  else {
    tft.print(myRTC.minutes);
  }
  int sensor = analogRead(A1);
  float voltage = (sensor * 5.0) / 1023;
  if (voltage != prevVolt)
  {
    prevVolt = voltage;
    battery();
  }
}

void drawDynMoreScreen() {
  buttons();
}

void drawDynDetailScreenTemp() {
  myRTC.updateTime();
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(5, 3);
  if (myRTC.dayofmonth < 10)
  {
    tft.print("0");
    tft.print(myRTC.dayofmonth);
  }
  else
  {
    tft.print(myRTC.dayofmonth);
  }
  tft.print("/");
  if (myRTC.month < 10) {
    tft.print("0");
    tft.print(myRTC.month);
  }
  else {
    tft.print(myRTC.month);
  }
  tft.print("/");
  tft.print(myRTC.year);
  tft.setCursor(206, 3);
  if (myRTC.hours < 10) {
    tft.print("0");
    tft.print(myRTC.hours);
  }
  else {
    tft.print(myRTC.hours);
  }
  tft.print(":");
  if (myRTC.minutes < 10) {
    tft.print("0");
    tft.print(myRTC.minutes);
  }
  else {
    tft.print(myRTC.minutes);
  }
  int sensor = analogRead(A1);
  float voltage = (sensor * 5.0) / 1023;
  if (voltage != prevVolt)
  {
    prevVolt = voltage;
    battery();
  }
}

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 = 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();
}

#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);
}

Thanks, that's better for my understanding (but still not enough to compile the whole sketch as the included libs are missing ...

This should work (hopefully :wink: ):

unsigned long previousMillis = 0;
const long interval = 1;

#include "Full.c"
#include "Draining.c"
#include "Drained.c"
#include "Empty.c"
#include "Charging.c"

#include "nonBlockingDS18B20.h"

enum machineStates {
  IDLE, WAITING_FOR_CONVERSION, ABORTED
};

const uint8_t ONE_WIRE_BUS = 2; // Change this to Pin # connected to OneWire bus
const uint8_t RESOLUTION = 12;
const unsigned long maxWaitTime = 5000;
const unsigned long interMeasurementPeriod = 1000;
machineStates currentState;
unsigned long measurementStartTime, measurementStopTime;
unsigned long interMeasurementTimer;

OneWire oneWire(ONE_WIRE_BUS);
nonBlockingDS18B20 tempSensors(&oneWire);

void printAddress(DeviceAddress);

uint8_t numDS18;

#define USE_TOUCH    0x2046

#include <virtuabotixRTC.h> //Libraries needed

virtuabotixRTC myRTC(6, 7, 8);

#include "Adafruit_GFX.h"    // Hardware-specific library
#include <MCUFRIEND_kbv.h>
#include <SPI.h>
#include <SD.h>
MCUFRIEND_kbv tft;       //
#define TFT_BEGIN()    tft.begin(0x9488)

#include <XPT2046_Touchscreen.h>           // Hardware SPI library
char *name = "Shield XPT2046 Calibration";  //edit name of shield
const int TS_LANDSCAPE = 1; //XPT2046_TouchScreen.h
const int TS_LEFT = 261, TS_RT = 3770, TS_TOP = 3869, TS_BOT = 296;
#define XPT_CS  53      // MEGA2560 SHIELD 
#define XPT_IRQ 255     // XPT2046 library does not like IRQ
XPT2046_Touchscreen ts(XPT_CS, XPT_IRQ);

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
  bool pressed = ts.touched();
  if (pressed) {
    TS_Point p = ts.getPoint();
    if (TS_LANDSCAPE) mapxy(p.y, p.x);
    else mapxy(p.x, p.y);
  }
  return pressed;
}

void Touch_init(void)
{
  ts.begin();
}

void mapxy(int x, int y)                //maps ADC to pixel_x, pixel_y
{
  int aspect = tft.getRotation();     //LANDSCAPE
  int tft_width = tft.width();
  int tft_height = tft.height();
  switch (aspect & 3) {
    case 0:      //PORTRAIT
      pixel_x = map(x, TS_LEFT, TS_RT, 0, tft_width);
      pixel_y = map(y, TS_TOP, TS_BOT, 0, tft_height);
      break;
    case 1:      //LANDSCAPE
      pixel_x = map(y, TS_TOP, TS_BOT, 0, tft_width);
      pixel_y = map(x, TS_RT, TS_LEFT, 0, tft_height);
      break;
    case 2:      //PORTRAIT REV
      pixel_x = map(x, TS_RT, TS_LEFT, 0, tft_width);
      pixel_y = map(y, TS_BOT, TS_TOP, 0, tft_height);
      break;
    case 3:      //LANDSCAPE REV
      pixel_x = map(y, TS_BOT, TS_TOP, 0, tft_width);
      pixel_y = map(x, TS_LEFT, TS_RT, 0, tft_height);
      break;
  }
}

Adafruit_GFX_Button temp_btn, humidity_btn, home_btn, more_btn;

#define BLACK 0x0000       /*   0,   0,   0 */
#define NAVY 0x000F        /*   0,   0, 128 */
#define DARKGREEN 0x03E0   /*   0, 128,   0 */
#define DARKCYAN 0x03EF    /*   0, 128, 128 */
#define MAROON 0x7800      /* 128,   0,   0 */
#define PURPLE 0x780F      /* 128,   0, 128 */
#define OLIVE 0x7BE0       /* 128, 128,   0 */
#define LIGHTGREY 0xC618   /* 192, 192, 192 */
#define DARKGREY 0x7BEF    /* 128, 128, 128 */
#define BLUE 0x001F        /*   0,   0, 255 */
#define GREEN 0x07E0       /*   0, 255,   0 */
#define CYAN 0x07FF        /*   0, 255, 255 */
#define RED 0xF800         /* 255,   0,   0 */
#define MAGENTA 0xF81F     /* 255,   0, 255 */
#define YELLOW 0xFFE0      /* 255, 255,   0 */
#define WHITE 0xFFFF       /* 255, 255, 255 */
#define ORANGE 0xFD20      /* 255, 165,   0 */
#define GREENYELLOW 0xAFE5 /* 173, 255,  47 */
#define PINK 0xF81F

uint8_t displayScreenNo, prevDay, prevMonth, prevSec, prevMin, prevHour, prevVolt, prevMoon;
uint16_t prevYear;

uint8_t index;
static float prevTemp = 999.99 ; // an unlikely value
float currentTempF = tempSensors.getLatestTempC(index);

String nfm = "";

#define SD_CS     48

#define NAMEMATCH ""
#define PALETTEDEPTH   8     // support 256-colour Palette

char namebuf[32] = "/";

File root;
int pathlen;

void setup() {
  //myRTC.setDS1302Time(00, 07, 18, 07, 9, 07, 2022);
  Serial.begin(2000000);
  numDS18 = tempSensors.begin(RESOLUTION);
  if (numDS18 == 0) {
    Serial.println(
      F("Did not locate any DS-type Temperature Sensors, aborting"));
    while (1) {
      delay(0);
    }
  }
  TFT_BEGIN();
  bool good = SD.begin(SD_CS);
  if (!good) {
    Serial.print(F("cannot start SD"));
    while (1);
  }
  Touch_init();
  tft.setRotation(1);            //PORTRAIT
  tft.fillScreen(BLACK);
  home_btn.initButton(&tft,  440, 280, 80, 80, LIGHTGREY, CYAN, BLACK, "HOME", 2);
  home_btn.drawButton(false);
  more_btn.initButton(&tft,  440, 40, 80, 80, LIGHTGREY, CYAN, BLACK, "MORE", 2);
  more_btn.drawButton(false);
  temp_btn.initButton(&tft,  440, 120, 80, 80, LIGHTGREY, CYAN, BLACK, "TEMP", 2);
  humidity_btn.initButton(&tft, 440, 200, 80, 80, LIGHTGREY, CYAN, BLACK, "%", 2);
  temp_btn.drawButton(false);
  humidity_btn.drawButton(false);
  tft.setTextSize(3);
}

void loop() {
  unsigned int IntensityOfLight;

  IntensityOfLight = analogRead(A0);

  myRTC.updateTime();

  bool down = Touch_getXY();
  home_btn.press(down && home_btn.contains(pixel_x, pixel_y));
  more_btn.press(down && more_btn.contains(pixel_x, pixel_y));
  temp_btn.press(down && temp_btn.contains(pixel_x, pixel_y));
  humidity_btn.press(down && humidity_btn.contains(pixel_x, pixel_y));
  if (home_btn.justReleased()) {
    home_btn.drawButton(true);
    more_btn.drawButton();
    temp_btn.drawButton();
    humidity_btn.drawButton();
  }
  if (more_btn.justReleased()) {
    more_btn.drawButton(true);
    home_btn.drawButton();
    temp_btn.drawButton();
    humidity_btn.drawButton();
  }
  if (temp_btn.justReleased()) {
    home_btn.drawButton();
    temp_btn.drawButton(true);
    more_btn.drawButton();
    humidity_btn.drawButton();
  }
  if (humidity_btn.justReleased()) {
    home_btn.drawButton();
    temp_btn.drawButton();
    humidity_btn.drawButton(true);
    more_btn.drawButton();
  }
  if (home_btn.justPressed())
  {
    tft.fillScreen(BLACK);
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    drawHomeScreen();
    displayScreenNo = 1;
    home_btn.drawButton(true);
    temp_btn.drawButton(false);
    humidity_btn.drawButton(false);
    more_btn.drawButton(false);
  }
  if (more_btn.justPressed())
  {
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    tft.fillScreen(BLACK);
    drawMoreScreen();
    displayScreenNo = 2;
    more_btn.drawButton(true);
    temp_btn.drawButton(false);
    humidity_btn.drawButton(false);
    home_btn.drawButton(false);
  }
  if (temp_btn.justPressed())
  {
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    tft.fillScreen(BLACK);
    drawDetailScreenTemp();
    displayScreenNo = 3;
    temp_btn.drawButton(true);
    home_btn.drawButton(false);
    humidity_btn.drawButton(false);
    more_btn.drawButton(false);
  }
  if (humidity_btn.justPressed())
  {
    prevDay = 99;
    prevMonth = 99;
    prevYear = 9999;
    prevHour = 99;
    prevMin = 99;
    prevSec = 99;
    prevTemp = 999.99;
    prevVolt = 9.99;
    tft.fillScreen(BLACK);
    drawDetailScreenHumidity();
    displayScreenNo = 4;
    humidity_btn.drawButton(true);
    temp_btn.drawButton(false);
    home_btn.drawButton(false);
    more_btn.drawButton(false);
  }
  switch (displayScreenNo)
  {
    case 1: drawDynHomeScreen(); break;
    case 2: drawDynMoreScreen(); break;
    case 3: drawDynDetailScreenTemp(); break;
    case 4: drawDynDetailScreenHumidity(); break;
  }
}

void drawHomeScreen() {
  tft.drawLine(0, 27, 480, 27, LIGHTGREY);
  tft.drawLine(0, 28, 480, 28, LIGHTGREY);
  tft.drawLine(200, 0, 200, 28, LIGHTGREY);
  tft.drawLine(201, 0, 201, 28, LIGHTGREY);

  tft.drawLine(0, 288, 480, 288, LIGHTGREY);
  tft.drawLine(0, 289, 480, 289, LIGHTGREY);
  tft.drawLine(200, 288, 200, 320, LIGHTGREY);
  tft.drawLine(201, 289, 201, 320, LIGHTGREY);
}

void drawDetailScreenHumidity() {

  tft.drawLine(0, 27, 480, 27, LIGHTGREY);
  tft.drawLine(0, 28, 480, 28, LIGHTGREY);
  tft.drawLine(200, 0, 200, 28, LIGHTGREY);
  tft.drawLine(201, 0, 201, 28, LIGHTGREY);


  tft.drawLine(27, 33, 339, 33, LIGHTGREY);
  tft.drawLine(27, 59, 339, 59, LIGHTGREY);
  tft.drawLine(27, 85, 339, 85, LIGHTGREY);
  tft.drawLine(27, 111, 339, 111, LIGHTGREY);
  tft.drawLine(27, 137, 339, 137, LIGHTGREY);
  tft.drawLine(27, 163, 339, 163, LIGHTGREY);
  tft.drawLine(27, 189, 339, 189, LIGHTGREY);
  tft.drawLine(27, 215, 339, 215, LIGHTGREY);
  tft.drawLine(27, 241, 339, 241, LIGHTGREY);
  tft.drawLine(27, 267, 339, 267, LIGHTGREY);
  tft.drawLine(27, 293, 339, 293, LIGHTGREY);

  tft.drawLine(339, 33, 339, 293, LIGHTGREY);
  tft.drawLine(313, 33, 313, 293, LIGHTGREY);
  tft.drawLine(287, 33, 287, 293, LIGHTGREY);
  tft.drawLine(261, 33, 261, 293, LIGHTGREY);
  tft.drawLine(236, 33, 236, 293, LIGHTGREY);
  tft.drawLine(209, 33, 209, 293, LIGHTGREY);
  tft.drawLine(183, 33, 183, 293, LIGHTGREY);
  tft.drawLine(157, 33, 157, 293, LIGHTGREY);
  tft.drawLine(131, 33, 131, 293, LIGHTGREY);
  tft.drawLine(105, 33, 105, 293, LIGHTGREY);
  tft.drawLine(79, 33, 79, 293, LIGHTGREY);
  tft.drawLine(53, 33, 53, 293, LIGHTGREY);
  tft.drawLine(27, 33, 27, 293, LIGHTGREY);

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(2, 33);
  tft.print("100%");
  tft.setCursor(6, 59);
  tft.print("90%");
  tft.setCursor(6, 85);
  tft.print("80%");
  tft.setCursor(6, 111);
  tft.print("70%");
  tft.setCursor(6, 137);
  tft.print("60%");
  tft.setCursor(6, 163);
  tft.print("50%");
  tft.setCursor(6, 189);
  tft.print("40%");
  tft.setCursor(6, 215);
  tft.print("30%");
  tft.setCursor(6, 241);
  tft.print("20%");
  tft.setCursor(6, 267);
  tft.print("10%");
  tft.setCursor(6, 293);
  tft.print("0%");

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(26, 300);
  tft.print("6");
  tft.setCursor(44, 300);
  tft.print("5.5");
  tft.setCursor(77, 300);
  tft.print("5");
  tft.setCursor(96, 300);
  tft.print("4.5");
  tft.setCursor(128, 300);
  tft.print("4");
  tft.setCursor(148, 300);
  tft.print("3.5");
  tft.setCursor(181, 300);
  tft.print("3");
  tft.setCursor(200, 300);
  tft.print("2.5");
  tft.setCursor(234, 300);
  tft.print("2");
  tft.setCursor(253, 300);
  tft.print("1.5");
  tft.setCursor(285, 300);
  tft.print("1");
  tft.setCursor(305, 300);
  tft.print("0.5");
  tft.setCursor(337, 300);
  tft.print("0");
}

void drawMoreScreen() {
  more_btn.drawButton(true);
}

void drawDetailScreenTemp() {

  tft.drawLine(0, 27, 480, 27, LIGHTGREY);
  tft.drawLine(0, 28, 480, 28, LIGHTGREY);
  tft.drawLine(200, 0, 200, 28, LIGHTGREY);
  tft.drawLine(201, 0, 201, 28, LIGHTGREY);

  tft.drawLine(27, 33, 339, 33, LIGHTGREY);
  tft.drawLine(27, 59, 339, 59, LIGHTGREY);
  tft.drawLine(27, 85, 339, 85, LIGHTGREY);
  tft.drawLine(27, 111, 339, 111, LIGHTGREY);
  tft.drawLine(27, 137, 339, 137, LIGHTGREY);
  tft.drawLine(27, 163, 339, 163, LIGHTGREY);
  tft.drawLine(27, 189, 339, 189, LIGHTGREY);
  tft.drawLine(27, 215, 339, 215, LIGHTGREY);
  tft.drawLine(27, 241, 339, 241, LIGHTGREY);
  tft.drawLine(27, 267, 339, 267, LIGHTGREY);
  tft.drawLine(27, 293, 339, 293, LIGHTGREY);

  tft.drawLine(339, 33, 339, 293, LIGHTGREY);
  tft.drawLine(313, 33, 313, 293, LIGHTGREY);
  tft.drawLine(287, 33, 287, 293, LIGHTGREY);
  tft.drawLine(261, 33, 261, 293, LIGHTGREY);
  tft.drawLine(236, 33, 236, 293, LIGHTGREY);
  tft.drawLine(209, 33, 209, 293, LIGHTGREY);
  tft.drawLine(183, 33, 183, 293, LIGHTGREY);
  tft.drawLine(157, 33, 157, 293, LIGHTGREY);
  tft.drawLine(131, 33, 131, 293, LIGHTGREY);
  tft.drawLine(105, 33, 105, 293, LIGHTGREY);
  tft.drawLine(79, 33, 79, 293, LIGHTGREY);
  tft.drawLine(53, 33, 53, 293, LIGHTGREY);
  tft.drawLine(27, 33, 27, 293, LIGHTGREY);

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(6, 33);
  tft.print("45");
  tft.print((char)247);
  tft.setCursor(6, 59);
  tft.print("40");
  tft.print((char)247);
  tft.setCursor(6, 85);
  tft.print("35");
  tft.print((char)247);
  tft.setCursor(6, 111);
  tft.print("30");
  tft.print((char)247);
  tft.setCursor(6, 137);
  tft.print("25");
  tft.print((char)247);
  tft.setCursor(6, 163);
  tft.print("20");
  tft.print((char)247);
  tft.setCursor(6, 189);
  tft.print("15");
  tft.print((char)247);
  tft.setCursor(6, 215);
  tft.print("10");
  tft.print((char)247);
  tft.setCursor(6, 241);
  tft.print(" 5");
  tft.print((char)247);
  tft.setCursor(6, 267);
  tft.print(" 0");
  tft.print((char)247);
  tft.setCursor(6, 285);
  tft.print("-5");
  tft.print((char)247);

  tft.setTextSize(1);
  tft.setTextColor(LIGHTGREY);
  tft.setCursor(26, 300);
  tft.print("6");
  tft.setCursor(44, 300);
  tft.print("5.5");
  tft.setCursor(77, 300);
  tft.print("5");
  tft.setCursor(96, 300);
  tft.print("4.5");
  tft.setCursor(128, 300);
  tft.print("4");
  tft.setCursor(148, 300);
  tft.print("3.5");
  tft.setCursor(181, 300);
  tft.print("3");
  tft.setCursor(200, 300);
  tft.print("2.5");
  tft.setCursor(234, 300);
  tft.print("2");
  tft.setCursor(253, 300);
  tft.print("1.5");
  tft.setCursor(285, 300);
  tft.print("1");
  tft.setCursor(305, 300);
  tft.print("0.5");
  tft.setCursor(337, 300);
  tft.print("0");
}

void battery () {
  int sensor = analogRead(A1);
  //Serial.println(sensor);
  float voltage = (sensor * 5.0) / 1023;
  //Serial.println(voltage);
  if (voltage > 3.65) {
    tft.drawRGBBitmap(355, 3, Charging, 36, 21);
  }
  if ((voltage <= 3.60) && (voltage > 3.20)) {
    tft.drawRGBBitmap(355, 3, Full, 36, 21);
  }
  if ((voltage <= 3.20) && (voltage > 2.80)) {
    tft.drawRGBBitmap(355, 3, Draining, 36, 21);
  }
  if ((voltage <= 2.80) && (voltage > 2.40)) {
    tft.drawRGBBitmap(355, 3, Drained, 36, 21);
  }
  if (voltage <= 2) {
    tft.drawRGBBitmap(355, 3, Empty, 36, 21);
  }
}

void buttons () {
  home_btn.drawButton(false);
  more_btn.drawButton(false);
  temp_btn.drawButton(false);
  humidity_btn.drawButton(false);
}
void drawDynHomeScreen() {
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  if (myRTC.dayofmonth != prevDay)
  {
    prevDay = myRTC.dayofmonth;
    tft.fillRect(5, 3, 33, 21, BLACK);
    tft.setCursor(5, 3);
    if (myRTC.dayofmonth < 10)
    {
      ShowMoonPhase();
      tft.print("0");
      tft.print(myRTC.dayofmonth);
    }
    else
    {
      ShowMoonPhase();
      tft.print(myRTC.dayofmonth);
    }
  }
  tft.setCursor(41, 3);
  tft.print("/");
  if (myRTC.month != prevMonth)
  {
    prevMonth = myRTC.month;
    tft.fillRect(59, 3, 33, 21, BLACK);
    tft.setCursor(59, 3);
    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.fillRect(113, 3, 70, 21, BLACK);
    tft.setCursor(113, 3);
    tft.print(myRTC.year);
  }
  if (myRTC.hours != prevHour)
  {
    prevHour = myRTC.hours;
    tft.fillRect(206, 3, 33, 21, BLACK);
    tft.setCursor(206, 3);
    if (myRTC.hours < 10) {
      tft.print("0");
      tft.print(myRTC.hours);
    }
    else {
      tft.print(myRTC.hours);
    }
  }
  tft.setCursor(239, 3);
  tft.print(":");
  if (myRTC.minutes != prevMin)
  {
    prevMin = myRTC.minutes;
    tft.fillRect(256, 3, 33, 21, BLACK);
    tft.setCursor(256, 3);
    if (myRTC.minutes < 10) {
      tft.print("0");
      tft.print(myRTC.minutes);
    }
    else {
      tft.print(myRTC.minutes);
    }
  }
  tft.setCursor(290, 3);
  tft.print(":");
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (myRTC.seconds != prevSec)
    {
      prevSec = myRTC.seconds;
      tft.fillRect(306, 3, 33, 21, BLACK);
      tft.setCursor(306, 3);
      if (myRTC.seconds < 10) {
        tft.print("0");
        tft.print(myRTC.seconds);
        Serial.print("0");
        Serial.println(myRTC.seconds);
      }
      else {
        tft.print(myRTC.seconds);
        Serial.println(myRTC.seconds);
      }
    }
  }
  int sensor = analogRead(A1);
  float voltage = (sensor * 5.0) / 1023;
  if (voltage != prevVolt)
  {
    prevVolt = voltage;
    battery();
  }
  uint8_t index;
  static uint32_t loopCount = 0;

  currentMillis = millis();
  switch (currentState) {
    case WAITING_FOR_CONVERSION:
      if (tempSensors.isConversionDone()) {
        // Measurement has finished print results
        measurementStopTime = currentMillis;
        Serial.print(F(" Sensors Took: "));
        Serial.print(measurementStopTime - measurementStartTime);
        Serial.println(F(" ms"));
        Serial.print(loopCount);
        Serial.println(F(" Iterations of loop occurred during this period."));
        // Print measurements from all temperature sensors
        for (index = 0; index < numDS18; index++) {
          Serial.print(F(" Results:  "));
          Serial.print(tempSensors.getLatestTempC(index), 2);
          Serial.println(F(" (C)"));
          if (currentTempF != prevTemp)
          {
            Serial.print(F("Temp values  "));
            Serial.print(prevTemp);
            Serial.print(F("  "));
            Serial.print(currentTempF);
            Serial.print(F("  "));
            prevTemp = tempSensors.getLatestTempC(index);
            Serial.println(prevTemp);
            tft.setCursor(5, 294);
            tft.fillRect(5, 294, 190, 21, BLACK);
            tft.print(tempSensors.getLatestTempC(index), 2);
            tft.print(" ");
            tft.print((char)247);
            tft.print("C");
          }
        }
        // Hang out until time for next measurement
        currentState = IDLE;
        interMeasurementTimer = currentMillis;
      } else if (currentMillis - measurementStartTime >= maxWaitTime) {
        Serial.println(F("Timed Out Waiting for Measurements to Complete -- Aborting"));
        currentState = ABORTED;
      }
      break;

    case IDLE:
      // Check if it's time to start another measurement
      if (currentMillis - interMeasurementTimer >= interMeasurementPeriod) {
        currentState = WAITING_FOR_CONVERSION;
        loopCount = 0;
        // Kick off another set of non-blocking sensor readings
        measurementStartTime = currentMillis;
        if (!tempSensors.startConvertion()) {
          Serial.println(F("Failed to Start Conversion Cycle, Aborting"));
          currentState = ABORTED;
        }
      }
      break;

    case ABORTED:
      break;
  }
  loopCount++;
}

void drawDynDetailScreenHumidity() {
  myRTC.updateTime();
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(5, 3);
  if (myRTC.dayofmonth < 10)
  {
    tft.print("0");
    tft.print(myRTC.dayofmonth);
  }
  else
  {
    tft.print(myRTC.dayofmonth);
  }
  tft.print("/");
  if (myRTC.month < 10) {
    tft.print("0");
    tft.print(myRTC.month);
  }
  else {
    tft.print(myRTC.month);
  }
  tft.print("/");
  tft.print(myRTC.year);
  tft.setCursor(206, 3);
  if (myRTC.hours < 10) {
    tft.print("0");
    tft.print(myRTC.hours);
  }
  else {
    tft.print(myRTC.hours);
  }
  tft.print(":");
  if (myRTC.minutes < 10) {
    tft.print("0");
    tft.print(myRTC.minutes);
  }
  else {
    tft.print(myRTC.minutes);
  }
  int sensor = analogRead(A1);
  float voltage = (sensor * 5.0) / 1023;
  if (voltage != prevVolt)
  {
    prevVolt = voltage;
    battery();
  }
}

void drawDynMoreScreen() {
  buttons();
}

void drawDynDetailScreenTemp() {
  myRTC.updateTime();
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(5, 3);
  if (myRTC.dayofmonth < 10)
  {
    tft.print("0");
    tft.print(myRTC.dayofmonth);
  }
  else
  {
    tft.print(myRTC.dayofmonth);
  }
  tft.print("/");
  if (myRTC.month < 10) {
    tft.print("0");
    tft.print(myRTC.month);
  }
  else {
    tft.print(myRTC.month);
  }
  tft.print("/");
  tft.print(myRTC.year);
  tft.setCursor(206, 3);
  if (myRTC.hours < 10) {
    tft.print("0");
    tft.print(myRTC.hours);
  }
  else {
    tft.print(myRTC.hours);
  }
  tft.print(":");
  if (myRTC.minutes < 10) {
    tft.print("0");
    tft.print(myRTC.minutes);
  }
  else {
    tft.print(myRTC.minutes);
  }
  int sensor = analogRead(A1);
  float voltage = (sensor * 5.0) / 1023;
  if (voltage != prevVolt)
  {
    prevVolt = voltage;
    battery();
  }
}

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 = 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;
}

// Returns false if moon_phase() was out of limits OR if showBMP() fails
// For showBMP return codes see the declaration of showBMP() 
boolean MoonPhaseBMPLoaded(int mp){
  if (0 <= mp && mp <= 7){
     char fname[10];   // Could be reduced to [8] ....
     sprintf(fname,"/0%d.bmp",mp+1);
     return (showBMP(fname, 3, 33) == 0);
  } else 
     return false;
}


void ShowMoonPhase(){
  int mp = moon_phase();
  if (!MoonPhaseBMPLoaded(mp)) {
     char message[80];   
     sprintf(message,"Error loading file /0%d.bmp",mp+1);
     Serial.println(message);
  }
}

#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)
{
/*
This function returns:

  0 : If non of the below applies and the rendering was ok
  1 : If the size of the BMP is wider and/or heigher than the tft.screen 
  2 : if the BMP does not have the ID 0x4D42, the "magic number" that marks a regular BMP 
  3 : If the BMP contains too many (bit-)planes (more than 1 in this case)
  4 : If the BMP is compressed or the colors are not 565 coded (16 Bit per pixel -> 5 Bit Red, 6 Bit Green 5 Bit blue)
  5 : If the BMP uses a palette (lookup table)

*/

  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);
}

As these parts are missing I could not compile it but just give it a try ...

#include "Full.c"
#include "Draining.c"
#include "Drained.c"
#include "Empty.c"
#include "Charging.c"

Just some explanations:

  • From your code (post 31) I saw that showBMP returns a value: "ret = showBMP("/01.bmp", 3, 33);" unfortunately not what the value is. So I assumed it as boolean. However now with the full sketch I was able to analyze the return value to be as follows:

uint8_t showBMP(char *nm, int x, int y) returns
0 : If none of the below applies and the rendering was ok
1 : If the size of the BMP is wider and/or heigher than the tft.screen
2 : if the BMP does not have the ID 0x4D42, the "magic number" that marks a regular BMP
3 : If the BMP contains too many (bit-)planes (more than 1 in this case)
4 : If the BMP is compressed or the colors are not 565 coded (16 Bit per pixel -> 5 Bit Red, 6 Bit Green 5 Bit blue)
5 : If the BMP uses a palette (lookup table)

  • The variable newNfm is declared and filled as a c string by nfm.c_str() at the end of the function "void moonPhase()" but never used. So I removed the line "const char* newNfm = (const char*) nfm.c_str();".

  • I supported the suggestion of @build_1971 and also @runaway_pancake to use more specific function names: void ShowMoonPhase() replaces moonPhase() and calls a function MoonPhaseBMPLoaded() that returns true if ok or false if not.

  • MoonPhaseBMPLoaded() returns false if the moonphase is outside of {0..7} or if showBMP() returns anything unequal to zero.

I hope that there is not typo (or any other kind of simple mistake) in the sketch :wink:

Looking forward to your results!

If you get any error messages please copy them to the forum like you copy sketches. That is easier to follow than screenshots!

Oops: Had to correct one line in the code ...

Instead of "return (showBMP(fname, 3, 33) != 0);" it must read " return (showBMP(fname, 3, 33) == 0);" of course ...

Please copy the version as it is now

Here is the reason for the error:

image

You did not replace the entire function "void moonPhase()" but copied "boolean moonPhase()" inside the function with the same name ...

However, getting the full sketch was better to exactly find out what showBMP() does return!

And if you ever may have trouble with reading a BMP you can of course use the other return data from showBMP() to find the reason.

P.S.: I added the mark at the end also ...

In the quoted original code from post 31 one can see that if moon_phase() is inside {0..7} the sketch will try to load a BMP which is named 0x.BMP with x = mp+1;

To avoid problems by invalid numbers when creating the filenames the if clause makes sure that only valid numbers are used. This way the function does not depend on a proper use (check for the valid range) at the place where it is called from:

boolean MoonPhaseBMPLoaded(int mp){
  if (0 <= mp && mp <= 7){      // This avoids problems if the function is called with mp out of the given range
     char fname[10];   // Could be reduced to [8] ....
     sprintf(fname,"/0%d.bmp",mp+1);
     return (showBMP(fname, 3, 33) == 0);
  } else 
     return false;
}

The limits could be provided as const values in the beginning of the sketch to make it more versatile. But that's a matter of the complete sketch design...

Hi,
I made this little moon phase calculator project, I hope it will help you :
moon_phase_calculator

@torlabs
I have a shorter working version of that exact idea:

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() {
  DateTime now = rtc.now();
  // 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 = now.now();
  double jd = 0; // Julian Date
  double ed = 0; //days elapsed since start of full moon
  int b = 0;
  jd = julianDate(now.year(), now.month(), now.day());
  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;
}

void moonPhase() {
  int mp = moon_phase();
  switch (mp) {
    case 0:
      ret = showBMP("/01.bmp", 25, 45);
      break;
    case 1:
      ret = showBMP("/02.bmp", 25, 45);
      break;
    case 2:
      ret = showBMP("/03.bmp", 25, 45);
      break;
    case 3:
      ret = showBMP("/04.bmp", 25, 45);
      break;
    case 4:
      ret = showBMP("/05.bmp", 25, 45);
      break;
    case 5:
      ret = showBMP("/06.bmp", 25, 45);
      break;
    case 6:
      ret = showBMP("/07.bmp", 25, 45);
      break;
    case 7:
      ret = showBMP("/08.bmp", 25, 45);
      break;
  }
  const char* newNfm = (const char*) nfm.c_str();
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.