Hardware issue with floating float switch [SOLVED]

For a diagnostics and datalogging device I've been building for a while now, I'm using a float switch to determine whether a water tanks water level is okay or not. I noticed that it would be an issue if there were any hardware connection problems, e.g. the float switch cable, for whatever reason, stops receiving signals, either by a disconnection, a loose connection etc. On my breadboard, I was using resistors to see if I could use an analogue pin and have differing values: I found that if I used a 100K resistor and placed it between the float switch pin (A3 pin) and GND, the values would be different and were consistent enough for me to be confident that I could use that in my circuit. The values I get on my PC's serial monitor from the analogue pin for the float switch is ~3600, with the exception of a few 4095 readings, which I've compensated for in my sketch. I have the circuit created on a Vero board and everything was working fine, until I tried to use my laptop as a power supply with a different cable. The readings I were getting were 4095 when the switch was open and connected. I tried the original cable on my laptop and it was still giving me a reading of 4095. I took the other cable to my PC and tried it, which gives me- again- 4095. I tested the voltage across VBUS and GND and I was getting ~5V on both cables and both computers. I have no idea why this is happening. I'll attach an image of my circuit and my sketch. Any help would be appreciated. Thanks!

Sketch:

//custom library
#include "Triogen.h"

//other libraries used
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <FS.h>
#include <RTClib.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Time.h>

//pin selection
#define RED_LED 1
#define GREEN_LED 2 
#define BLUE_LED 3
#define BUZZER_TOGGLE_SWITCH 5
#define RED_ALARM 6
#define GREEN_ALARM 7
#define BUZZER_PIN 8
#define CHIP_SELECT 21

//set reset vector at address 0 - essentially does a reset on the board once called
void (*resetFunc)(void) = 0;

//lcd pin configurations
LiquidCrystal_I2C lcd(0x27, 20, 4);

//time variables
RTC_DS3231 rtc;
time_t now; 
struct tm myTimeInfo;
unsigned long tStart = millis();
unsigned long totMillis;
int totSeconds;
int totMinutes;
int totHours;
int totDays;
unsigned long lastMillis = 0;
const unsigned long SAMPLE_TM = 1250;
unsigned long tSample = totMillis + SAMPLE_TM;
const unsigned long WATER_ICON_TM = 250;
unsigned long tIcon = totMillis + WATER_ICON_TM;
static int year;
static int month;
static int day;
static int hour;
static int minute;
static int second;

char dayName[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char monthName[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

//toggle alarm 
bool buzzerPinState;
bool BTstate; 
bool buzzerPinOutState;

//blink and bleep without delay
bool outputState; 

//count errors to only print error once per logging interval
uint8_t errCount = 0;

int totalErrorCount = 0;

//number of samples
uint8_t nSample = 1;

//ensure the new file functions are only ran once if the time is 00:00:00
uint8_t funcPassThru = 0;

uint8_t iconNo = 1;

//SD card global variables
char dirName[9] = "/TANKLOG";

//fileName and fullPath specified 24 uint8_ts to avoid format overflow
char fileName[24];
char fullPath[24];
File dataFile;

//get time from NTP server and use WiFi
const char* NTP_SERVER = "pool.ntp.org";
const long GMT_OFFSET_SEC = 0;  
const int DAYLIGHT_OFFSET_SEC = 3600;
const char* TIME_ZONE = PSTR("GMT0BST,M3.5.0/1,M10.5.0");
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", GMT_OFFSET_SEC);
int WiFiTimeout;

//only used for water tank logging (change for any other type of data)
#include <OneWire.h>
#include <DallasTemperature.h>
#define floatSw 4
#define tempResolution 12
#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DeviceAddress tankTempSensor;
DallasTemperature sensors(&oneWire);
int floatValue;

//temperature variables 
static float totT1;
float aveT1;
static float tempC;

//buffers for float to string conversion for formatting data
char charAveT1[6];
char charTotT1[8];
char charTemp[8];

//error flags 
bool floatErrState = 0;
bool tempErrState = 0;
bool highTempErrState = 0;

//alarm icons
uint8_t SPEAKER_ICON[8]          =   {B00001, B00011, B00111, B11111, B11111, B00111, B00011, B00001};
uint8_t ALARM_ON_ICON[8]         =   {B00010, B01001, B00101, B10101, B10101, B00101, B01001, B00010};
uint8_t ALARM_OFF_ICON[8]        =   {B00000, B00000, B01010, B00100, B00100, B01010, B00000, B00000};
   
//water tank diagnostic icons 
uint8_t THERMOMETER_ICON[8]      =   {B00100, B01010, B01010, B01010, B01110, B11111, B11111, B01110};
uint8_t WATER_1_ICON[8]          =   {B00100, B00100, B01010, B01010, B10001, B10001, B10001, B01110};
uint8_t WATER_2_ICON[8]          =   {B00100, B00100, B01010, B01010, B10001, B10001, B11111, B01110};
uint8_t WATER_3_ICON[8]          =   {B00100, B00100, B01010, B01010, B10001, B11111, B11111, B01110};
uint8_t WATER_4_ICON[8]          =   {B00100, B00100, B01010, B01010, B11111, B11111, B11111, B01110};
uint8_t WATER_5_ICON[8]          =   {B00100, B00100, B01010, B01110, B11111, B11111, B11111, B01110};
uint8_t WATER_6_ICON[8]          =   {B00100, B00100, B01110, B01110, B11111, B11111, B11111, B01110};

//runtime icons  
uint8_t RUNTIME_L_ICON[8]        =   {B00001, B00000, B01001, B11101, B01001, B01000, B00100, B00011};
uint8_t RUNTIME_R_ICON[8]        =   {B11000, B00100, B00010, B00010, B11010, B00010, B00100, B11000};
  
//signal icons  
uint8_t SIGNAL_1_BAR_ICON[8]      =  {B11111, B10001, B01010, B00100, B00100, B00000, B00000, B10000};
uint8_t SIGNAL_2_BAR_ICON[8]      =  {B11111, B10001, B01010, B00100, B00100, B00000, B00100, B10100};
uint8_t SIGNAL_3_BAR_ICON[8]      =  {B11111, B10001, B01010, B00100, B00100, B00001, B00101, B10101};
uint8_t SIGNAL_4_BAR_ICON[8]      =  {B00000, B00000, B00000, B00000, B10000, B10000, B10000, B10000};
uint8_t SIGNAL_CLEAR_ICON[8]      =  {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000};
uint8_t NO_SIGNAL_ICON[8]         =  {B00000, B00000, B10100, B01000, B10100, B00001, B00101, B10101};

//function runs if SD card or RTC is not connected
void hardwareErr() {

  analogWrite(RED_LED, 0);
  analogWrite(BLUE_LED, 0);

  while (!SD.begin() || !rtc.begin()) {
    digitalWrite(BUZZER_PIN, 1);
    analogWrite(GREEN_LED, 175);
    delay(500);
    digitalWrite(BUZZER_PIN, 0);
    analogWrite(GREEN_LED, 0);
    delay(1500);
  }

  if(SD.begin(CHIP_SELECT) && rtc.begin()) {
    lcd.clear();
    resetFunc();
  }
}

//show the reason for the last reset of the ESP32
int printResetReason() {

  Serial.print("\n\n\n");
  int reason = esp_reset_reason();
  Serial.printf("CPU reset reason: %d\n", reason);

  switch (reason) {

    case ESP_RST_UNKNOWN: Serial.println("unknown"); break;
    case ESP_RST_POWERON: Serial.println("POWER ON RESET"); break;
    case ESP_RST_SW: Serial.println("SOFTWARE RESET"); break;
    case ESP_RST_PANIC: Serial.println("PANIC RESET"); break;
    case ESP_RST_TASK_WDT: Serial.println("TASK WDT RESET"); break;
    case ESP_RST_WDT: Serial.println("OTHER WDT RESET"); break;
    case ESP_RST_DEEPSLEEP: Serial.println("EXIT DEEP SLEEP RESET"); break;
    case ESP_RST_BROWNOUT: Serial.println("BROWNOUT RESET"); break;
    case ESP_RST_SDIO: Serial.println("SDIO RESET"); break;
  }
  
  return(reason);
}

//print hexadecimal address of DS18B20 temperature sensor
void printAddress(DeviceAddress tankTempSensor) {

  for (uint8_t i = 0; i < 8; i++) {

    if(tankTempSensor[i] < 16) Serial.print("0");
      Serial.print(tankTempSensor[i], HEX);
    }
}

//initialise pin configurations and begin serial communication and LCD
void init() {

  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUZZER_TOGGLE_SWITCH, INPUT_PULLUP);
  pinMode(floatSw, INPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
  pinMode(RED_ALARM, OUTPUT);
  pinMode(GREEN_ALARM, OUTPUT);

  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  digitalWrite(BLUE_LED, LOW);
  lcd.begin(20, 4);
  delay(2000);
  lcd.setBacklight(255);
  lcd.clear();
}

//initialise the DS18B20 temperature sensor
void initDS18B20() {

  sensors.begin();
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  Serial.print("DS18B20 Address: ");
  sensors.getAddress(tankTempSensor, 0);
  printAddress(tankTempSensor); 
  Serial.print("\n");  
  sensors.setResolution(tankTempSensor, tempResolution);
}

//initialise the SD card
void initSD() {
  SD.begin(CHIP_SELECT);
  lcd.setCursor(0, 0);
  printAll("Initialising SD...");
  delay(1000);

  if(!SD.begin()) {
    lcd.clear();
    printAll("SD card failed.");
    lcd.setCursor(0, 1);
    lcd.print("Check that the SD");
    lcd.setCursor(0, 2);
    lcd.print("is present and all");
    lcd.setCursor(0, 3);
    lcd.print("wiring is correct");
    Serial.println("Check that the SD card is mounted and all wiring and connections have been made and are correct.");
    hardwareErr();
  }

  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE) {
    lcd.clear();
    printAll("No SD card attached");
    hardwareErr();
  }

  Serial.print("SD Card Type: ");

  if(cardType == CARD_MMC) { 
    Serial.println("MMC"); 
  } 

    else if(cardType == CARD_SD) {
      Serial.println("SDSC");
  } 

    else if(cardType == CARD_SDHC) {
      Serial.println("SDHC");
  }
  
  else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
}

//initialise the RTC
void initRTC(){

  lcd.setCursor(0, 1);
  printAll("Initialising RTC...");
  delay(1000);

  if(!rtc.begin()) {
    lcd.clear();
    printAll(F("RTC failed."));
    lcd.setCursor(0, 1);
    lcd.print("Check that the RTC");
    lcd.setCursor(0, 2);
    lcd.print("is wired and mounted");
    lcd.setCursor(0, 3);
    lcd.print("correctly.");
    Serial.println("Check that the RTC is mounted and all wiring and connections have been made and are correct");
    hardwareErr();
  }

  lcd.clear();
  lcd.setCursor(0, 0);
}

//initialise WiFi
void initWiFi() {

  Serial.print("Connecting to WiFi...");
  lcd.print("Connecting to WiFi..");
  WiFi.begin(Triogen_ssid, Triogen_password);

  while(WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
    WiFiTimeout+=1;

    if(WiFiTimeout == 15) {
      Serial.print("\nCannot connect to WiFi. time will derive from last time set on RTC and offline mode will be used instead.\n\n");
      lcd.clear();
      lcd.print("No WiFi available");
      lcd.setCursor(0,2);
      lcd.print("Offline mode will");
      lcd.setCursor(0,3);
      lcd.print("be used instead");
      digitalWrite(BUZZER_PIN, HIGH);
      delay(100);
      digitalWrite(BUZZER_PIN, LOW);
      delay(100);
      digitalWrite(BUZZER_PIN, HIGH);
      delay(100);
      digitalWrite(BUZZER_PIN, LOW);
      delay(100);
      digitalWrite(BUZZER_PIN, HIGH);
      delay(100);
      digitalWrite(BUZZER_PIN, LOW);
      delay(4500);

      DateTime now = rtc.now();
      year = now.year();
      month = now.month();
      day = now.day();
      hour = now.hour();
      minute = now.minute();
      second = now.second();
      break;
    }
  }

  if(WiFi.status() == WL_CONNECTED){
    lcd.setCursor(0, 1);
    Serial.println();
    printAll("WIFI CONNECTED");
    initNTPtime();
  }
}

//initialise NTP and get time (function only runs if WiFi is connected)
void initNTPtime() {

  timeClient.begin();
  timeClient.update();
  
  lcd.setCursor(0, 3);
  Serial.printf("Getting time from %s...", NTP_SERVER);
  lcd.setCursor(0, 2);
  lcd.print("Getting time from   ");
  lcd.setCursor(0, 3);
  lcd.print(NTP_SERVER);
  lcd.print("...     ");
  time(&now);
  localtime_r(&now, &myTimeInfo);
  configTime(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER);

  while(!getLocalTime(&myTimeInfo)) {
    Serial.print(".");
  }
  
  year   = myTimeInfo.tm_year + 1900; 
  month  = myTimeInfo.tm_mon + 1;    
  day    = myTimeInfo.tm_mday;
  hour   = myTimeInfo.tm_hour;
  minute = myTimeInfo.tm_min;
  second = myTimeInfo.tm_sec; 

  char NTPtime[70];
  rtc.adjust(DateTime(year, month, day, hour, minute, second));
  sprintf(NTPtime, "Date: %02d-%02d-%02d Time: %02d:%02d:%02d", day, month, year, hour, minute, second);
  Serial.println();
  Serial.println(NTPtime);
}

//create the file name and directory for data logging
void createFileName() {

  sprintf(fileName, "%02d-%02d-%d.txt", day, month, year - 2000);
  strlcpy(fullPath, dirName, sizeof fullPath);
  strlcat(fullPath, "/", sizeof fullPath);
  strlcat(fullPath, fileName, sizeof fullPath);
  SD.mkdir(dirName);
  Serial.printf("Full File Path: X:%s \n\n", fullPath);
}

//first write to the file created in the SD card
void firstWrite() {

  uint8_t date = strlen(fileName)-4;
  fileName[date] = '\0';
  dataFile = SD.open(fullPath, FILE_APPEND);
  dataFile.printf("Date: %s\n", fileName);
  dataFile.println("Time(s),Sw State,Temp(°C)");
  dataFile.close();

  lcd.clear();
}

//all time information relevant for loop
void timeInfo() {

  //use rtc time for data logging 
  DateTime now = rtc.now();
  year   = now.year(); 
  month  = now.month() - 1;
  day    = now.day();
  hour   = now.hour();
  minute = now.minute();
  second = now.second();

  int DoW = now.dayOfTheWeek();
  int formattedHour = hour;

  lcd.setCursor(18, 1);

  switch(hour) {

    case 0:
      formattedHour = hour + 12;
      lcd.print("am");
    break;

    case 1 ... 11:
      formattedHour = hour;
      lcd.print("am");
    break;

    case 12:
      formattedHour = hour;
      lcd.print("pm");
      break;

      case 13 ... 23:
        formattedHour = hour - 12;
        lcd.print("pm");
      break;
  }

  lcd.setCursor(6, 1);

  switch(day) {

    case 1:
    case 21:
    case 31:
      lcd.print("st");
    break;

    case 2:
    case 22:
      lcd.print("nd");
     break;

    case 3:
    case 23:
      lcd.print("rd");
     break;

    case 4 ... 20:
    case 24 ... 30:
      lcd.print("th");
    break;
  }


  char runtime[24];
  char DoWday[8];
  char monthTime[16];

  if(!rtc.begin()) {
    lcd.clear();
    printAll(F("RTC failed"));
    hardwareErr();
  }
  
  //create new file if a new day occurs 
  if(hour == 0 && minute == 0 && second == 0 && funcPassThru <= 2) {
    funcPassThru += 1;
    createFileName();
    firstWrite();
  } 

  sprintf(DoWday, "%s %02d", dayName[DoW], day);
  sprintf(monthTime, "%s %2d:%02d", monthName[month], formattedHour, minute);
  lcd.setCursor(0, 1);
  lcd.print(DoWday);
  lcd.setCursor(9, 1);
  lcd.print(monthTime);

  //total run time of datalogging
  totMillis = millis() - tStart;
  totSeconds = totMillis / 1000;
  totMinutes = totSeconds / 60;
  totHours = totMinutes / 60;
  totDays = totHours / 24;

  totSeconds %= 60;
  totMinutes %= 60;
  totHours %= 24;
  totDays %= 7;

  char charDays[2];
  char charHours[3];
  char charMinutes[3];
  char charSeconds[3];

  //these values are converted to formatted strings as float values cannot be used in sprintf
  dtostrf(totDays, 1, 0, charDays);
  dtostrf(totHours, 2, 0, charHours);
  dtostrf(totMinutes, 2, 0, charMinutes);

  dtostrf(totSeconds, 2, 0, charSeconds);
  sprintf(runtime, "%sd%sh%sm%ss", charDays, charHours, charMinutes, charSeconds);
  lcd.setCursor(2, 0);
  lcd.print(runtime);

  funcPassThru = 0;
}

//create and write custom characters for LCD 
void customChars() {

  //changes the alarm icon that is displayed whenever the alarm is on of off
  if(buzzerPinOutState == 1) {
    lcd.createChar(3, ALARM_ON_ICON);
  }
  else if(buzzerPinOutState == 0) {
    lcd.createChar(3, ALARM_OFF_ICON);
  }

  if(totMillis > tIcon) {
    iconNo += 1;
    tIcon += WATER_ICON_TM;
  }

  if(floatValue >= 1500 && floatValue <= 2600) {
    switch(iconNo) {
      case 1:
        lcd.createChar(4, WATER_1_ICON);
      break;

      case 2:
        lcd.createChar(4, WATER_2_ICON);
      break;

      case 3:
        lcd.createChar(4, WATER_3_ICON);
      break;

      case 4:
        lcd.createChar(4, WATER_4_ICON);
      break;

      case 5:
        lcd.createChar(4, WATER_5_ICON);
      break;

      case 6:
        lcd.createChar(4, WATER_6_ICON);
      break;

    }

    if(iconNo > 6) {

      iconNo = 1;
    }
  }

  else {

    lcd.createChar(4, WATER_6_ICON);
  }

  int signalStrength = WiFi.RSSI();

  if(WiFi.status() != WL_CONNECTED) {
    lcd.createChar(6, NO_SIGNAL_ICON);
    lcd.createChar(7, SIGNAL_4_BAR_ICON);
  }

  //switch case statements are causing errors in the writing of these characters,
  //therefore else if statements are being used instead
  else if (signalStrength <= -90) {
    lcd.createChar(6, SIGNAL_1_BAR_ICON);
    lcd.createChar(7, SIGNAL_CLEAR_ICON);
  }

  else if (signalStrength >= -89 && signalStrength <= -80) {
    lcd.createChar(6, SIGNAL_2_BAR_ICON);
    lcd.createChar(7, SIGNAL_CLEAR_ICON);
  }

  else if (signalStrength >= -79 && signalStrength <= -70) {
    lcd.createChar(6, SIGNAL_3_BAR_ICON);
    lcd.createChar(7, SIGNAL_CLEAR_ICON);
  }

  else if (signalStrength >= -69) {
    lcd.createChar(6, SIGNAL_3_BAR_ICON);
    lcd.createChar(7, SIGNAL_4_BAR_ICON);
  }

  lcd.createChar(0, SPEAKER_ICON);
  lcd.createChar(1, RUNTIME_L_ICON);
  lcd.createChar(2, RUNTIME_R_ICON);
  //3 is dynamic dependent on conditions
  //4 is dynamic dependent on conditions
  lcd.createChar(5, THERMOMETER_ICON);
  //6 is dynamic dependent on conditions
  //7 is dynamic dependent on conditions

  lcd.setCursor(14, 0);
  lcd.write(0);
  lcd.setCursor(0, 0);
  lcd.write(1);
  lcd.setCursor(1, 0);
  lcd.write(2);
  lcd.setCursor(15, 0);
  lcd.write(3);
  lcd.setCursor(0, 3);
  lcd.write(4);
  lcd.setCursor(0, 2);
  lcd.write(5);
  lcd.setCursor(17, 0);
  lcd.write(6);
  lcd.setCursor(18, 0);
  lcd.write(7);

}

//check the temperature and float error states 
void checkForErrs() {

  //time intervals for all possible error states
  const int FLOAT_SW_TM = 500;
  const int HIGH_TEMP_TM = 750;
  const int TEMP_ERR_TM = 1000;
  const int TEMP_FLOAT_ERR_TM = 250;
  const int HIGH_TEMP_FLOAT_ERR_TM = 125;

  if(totalErrorCount >= 1) {

    lcd.setCursor(19, 0);
    lcd.print("*");
  }
  
  
  //if float switch is "NOT OK"
  if(floatErrState == 1 && tempErrState == 0 && highTempErrState == 0) {

    if(totMillis - lastMillis >= FLOAT_SW_TM) {
      lastMillis = totMillis;

      if(outputState == 0) {
        outputState = 1;
      }

      else {
        outputState = 0;
      }
    } 

    if(buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    }

    else {
      digitalWrite(BUZZER_PIN, 0);
    }
      
    if(outputState == 1) {
      analogWrite(RED_LED, 0);
      analogWrite(GREEN_LED, 0);
    }

    analogWrite(BLUE_LED, outputState * 255);
  }
  //if a temperature error occurs (-127 or 85)
  if(tempErrState == 1 && floatErrState == 0) {

    if(totMillis - lastMillis >= TEMP_ERR_TM) {
      lastMillis = totMillis;

      if(outputState == 0) {
        outputState = 1;
      }

      else {
        outputState = 0;
      }
    } 

    if(buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    }

    else {
      digitalWrite(BUZZER_PIN, 0);
    }

    analogWrite(RED_LED, outputState * 255);
    analogWrite(GREEN_LED, outputState * 255);
    analogWrite(BLUE_LED, outputState * 255);

    if(errCount <= 1) {
      dataFile = SD.open(fullPath, FILE_APPEND);
      dataFile.print("ERROR:");
      dataFile.close();
      Serial.print("ERROR: ");
      errCount+=1;
    }
  }
  //if the temperature is very high
  if(highTempErrState == 1 && floatErrState == 0) {
    lcd.setCursor(12, 1);


    if(totMillis - lastMillis >= HIGH_TEMP_TM) {
      lastMillis = totMillis;

      if(outputState == 0) {
        outputState = 1;
      }

      else {
        outputState = 0;
      }
    } 

    if(buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    }

    else {
      digitalWrite(BUZZER_PIN, 0);
    }

    if(outputState == 1) {
      analogWrite(GREEN_LED, 0);
      analogWrite(BLUE_LED, 0);
    }

    analogWrite(RED_LED, outputState * 255);
  } 
  //float error and temperature error
  if(floatErrState == 1 && tempErrState == 1) {
    
    if(totMillis - lastMillis >= TEMP_FLOAT_ERR_TM) {
      lastMillis = totMillis;

      if(outputState == 0) {
        outputState = 1;
      }

      else {
        outputState = 0;
      }
    } 

    if(buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    }

    else {
      digitalWrite(BUZZER_PIN, 0);
    }

      //flash blue for float error
      analogWrite(BLUE_LED, 255);
      //then flash white for temperature error
      analogWrite(RED_LED, outputState * 255);
      analogWrite(GREEN_LED, outputState * 255);
  }
  //float error and high temperature
  if(floatErrState == 1 && highTempErrState == 1) {

    if(totMillis - lastMillis >= HIGH_TEMP_FLOAT_ERR_TM) {
      lastMillis = totMillis;

      if(outputState == 0) {
        outputState = 1;
      }

      else {
        outputState = 0;
      }
    } 

    if(buzzerPinOutState == 1) {
      digitalWrite(BUZZER_PIN, outputState);
    }

    else {
      digitalWrite(BUZZER_PIN, 0);
    }
    
      analogWrite(BLUE_LED, outputState * 255);
      analogWrite(RED_LED, !outputState * 255); 
  }
  //changes the output state to 0 and sends a low signal to buzzer to ensure hardware isn't stuck
  //in a constant error state (e.g. buzzer HIGH or RGB LED constant BLUE_LED)
  if(floatErrState == 0 && tempErrState == 0 && highTempErrState == 0) {
    outputState = 0;
    digitalWrite(BUZZER_PIN, 0);
  }
}

//check the state of the float switch to check if the water tank is over flowing
void checkFloatState() {

  lcd.setCursor(2, 3);

  floatValue = analogRead(floatSw);
  static int floatSmoothingError = 0;

  if(floatValue >= 1500 && floatValue <= 3700) {
    lcd.print("WATER LEVEL OK    ");
    floatErrState = 0;
    floatSmoothingError = 0;
  } 
  
  else if(floatValue < 200) {
    lcd.print("WATER LEVEL HIGH");
    floatErrState = 1;
    floatSmoothingError = 0;
  }

  
  else if (floatValue > 4000) {
    floatSmoothingError += 1;
  }

  if(floatSmoothingError >= 5) {
    lcd.print("NO SWITCH FOUND ");
    floatErrState = 1;
    totalErrorCount += 1;
  }

  Serial.println(floatValue);
}

//check the temperature of the water tank to ensure the water is not too hot for cooling
void checkTemp() {

  //if temperature is a valid value
  if(tempC >-127 && tempC < 85) {
  
    lcd.setCursor(2, 2);
    lcd.print(tempC);
    lcd.print("\337C           ");
    tempErrState = 0;
  }

  //so temperature values can be used in a switch case statement (easier for code readability)
  int intTemp = floor(tempC);
  
  switch(intTemp) {

    case -127:
      tempErrState = 1;
      lcd.setCursor(2, 2);
      lcd.print("NO SENSOR FOUND   ");
      break;
      
    case 4 ... 25:  
      if(outputState == 0) {
        analogWrite(RED_LED, 0);   
        analogWrite(GREEN_LED, 255); 
        analogWrite(BLUE_LED, 0); 
      }
      highTempErrState = 0;
    break;

    case 26 ... 28: 
      if(outputState == 0) {
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 255);
        analogWrite(BLUE_LED, 0); 
      }
      highTempErrState = 0;
    break;

    case 29 ... 31: 
      if(outputState == 0) {
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 70);
        analogWrite(BLUE_LED, 0);
      }
      highTempErrState = 0;
    break;

    case 32 ... 34:
      if(outputState == 0) {
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 0);
        analogWrite(BLUE_LED, 0);
      }
      highTempErrState = 0;
    break;

    case 35 ... 84: 
      highTempErrState = 1;
    break;

    case 85:
      tempErrState = 1;
      lcd.setCursor(2, 2);
      lcd.print("CONVERSION ERROR  ");
      break;
  }
} 

//sample the data 
void sampleData() {

  //store temperature in a float variable
  tempC = sensors.getTempCByIndex(0);

  char sampleData[150];

  //sample data within the sampling interval
  if(totMillis > tSample) {
    totT1 = tempC + totT1;
    aveT1 = totT1 / nSample;
    dtostrf(aveT1, 5, 2, charAveT1);
    dtostrf(totT1, 7, 2, charTotT1);
    dtostrf(tempC, 7, 2, charTemp);
    sprintf(sampleData, "Time: %02d:%02d:%02d | Runtime: %02dd %02dh %02dm %02ds | Sample: %d | Sw: %d | temp(°C):%s | Ave:  %s | Tot:%s\n",
    hour, minute, second, totDays, totHours, totMinutes, totSeconds,
    nSample, !floatErrState, charTemp, charAveT1, charTotT1);
    Serial.print(sampleData);
    nSample +=1;
    tSample += SAMPLE_TM;
    sensors.requestTemperatures();
  }

  aveT1 = totT1 / nSample;
}

//log the data
void logData() {

  //converts the time of day to seconds for the logging file
  unsigned long hToM = hour * 60;
  unsigned long hToS = hToM * 60;
  unsigned long mToS = (minute * 60);
  unsigned long sToS = second;
  unsigned long tmDayInS = hToS + mToS + sToS;

  char aveData[20];
  char charTmDayInS[7];
  dtostrf(tmDayInS, 5, 0, charTmDayInS);
  sprintf(aveData, "%s,%d,%s", charTmDayInS, !floatErrState, charAveT1);

  dataFile = SD.open(fullPath, FILE_APPEND);

  if(!dataFile) {
    lcd.clear();
    printAll(F("File write Err"));
    hardwareErr();
  } 

  static int logCount = 0;

  if(nSample == 9) {
    nSample -=1;
    dataFile.println(aveData);
    dataFile.close();
    logCount+=1;
    Serial.printf("\n LOG NO.%d\n", logCount);
    Serial.println("| Time(s) | Float Switch State | Average Temperature(°C) |");
    Serial.printf("|  %s  |         %d          |          %s          |\n\n",
    charTmDayInS, !floatErrState, charAveT1);
    totT1 = 0;
    nSample = 1;
    errCount = 0;
  }
}

//all relevant code for alarm, as well as button debouncing
void alarmFunc() {
  
  static bool lastBTstate = 0;
  unsigned long lastDebounceTime = 0;
  const uint8_t DEBOUNCE_DELAY = 50;
  bool newBTstate = digitalRead(BUZZER_TOGGLE_SWITCH);

  if(newBTstate != lastBTstate) {
    lastDebounceTime = totMillis;
  }

  if((totMillis - lastDebounceTime) > DEBOUNCE_DELAY) {

    if(newBTstate != BTstate) {
      BTstate = newBTstate;

      if(BTstate == 1) {
        buzzerPinState = !buzzerPinState;
      }
    }
  }

  lcd.setCursor(7, 0);

  if(buzzerPinState == 1) {
    buzzerPinOutState = 1;
   
    digitalWrite(RED_ALARM, LOW);
    digitalWrite(GREEN_ALARM, HIGH);
    
  }

  else if(buzzerPinState == 0) {
    buzzerPinOutState = 0;
   
    digitalWrite(GREEN_ALARM, LOW);
    digitalWrite(RED_ALARM, HIGH);
  }

  lastBTstate = newBTstate;
}


//setup function
void setup() {
  
  Wire.begin();
  Serial.begin(BAUD);
  delay(1500); 
  Wire.setClock(400000);

  printResetReason();
  init();
  initDS18B20();
  initSD();
  initRTC();
  initWiFi();
  createFileName();
  firstWrite();

  tStart = millis();
}


//loop function
void loop() {
  
  timeInfo();
  customChars();
  checkForErrs();
  checkFloatState();
  checkTemp();
  sampleData();
  logData();
  alarmFunc();
}

// END OF PROGRAM
/********************************************************************************************************************************************************************************/

Please post your sketch as well as a wiring diagram.

You're image shows a Nano as far as I can see; a Nano will never produce an analogue reading of 4095.

Sorry, I forgot to change the circuit- I am using a Nano ESP32 now instead. I'll change it in a minute.

What software do you use for wiring diagrams? I don't have any software for that. Would Fritzing be a good choice?

Pencil and paper :wink: Take a photo and post it in a reply.

Most people frown on Fritzing; it often results in a mess or spaghetti.

I often use Kicad but there are others. I don't do much design work though.

If think this will solve your problem.
The 22K is soldered directly across the switch terminals.

Buy a new keyboard with a RETURN/ENTER key.

1 Like

Thanks for the input, it didn't help with the issue I'm having but I now finally have a sense of humour!

1 Like

That circuit is foolproof. You must be doing something wrong

Sorry, I was responding to post #6. I'm trying that circuit out just now. Thank you

That fixed it! Now I'm getting <20mV closed, ~2.5V open and ~3.8V when disconnected. I had to use a 10K as opposed to a 22K as I have no 22K resistors on hand, and I'm running it at 5V but it's worked very well. Thank you for the help!

Edit: may I ask what software you are using for the design?

You shouldn't. The Nano ESP32 I/O are 3.3V ONLY. You will damage the Nano

Software is KiCAD

Two of them in series gives you 20K

The LCD I'm using only really works on 5V (if it is ran on 3.3v, it is very, very dim) and I tried using the VBUS pin instead, which has been working well for weeks.

My 2004 LCD is using an I2C backpack, so should I use an external power supply for the LCD's VCC and GND pins?

I am aware, but using a 10K resistor has worked well too. I'm just trying to preserve as many resources as possible!

Use the Nano 3.3V output for the switch circuit.
With two 10Ks you will get 1.65V when connected and 3.3V when not

But can I run the LCD from VBUS or should I use an external power supply? I only need 5V on my LCD

You can power it using VBUS but you should have an I2C voltage translator to go from the 5V to 3.3V

I'm looking at that just now, just need to find a way to implement it into my project.

Can I also use it with just a basic buzzer? I want the buzzer to be ran on 5V too as I need it to be as loud as possible

Yes but the VBUS current limit will be whatever you computer can supply, which is normally limited to 500mA.
I assume you want to turn the buzzer off and on and you will need a transistor to do that.

I assume I could also make this logic level converter myself?

As it is a little bit big, it would make my circuit quite a big larger.