Problem With Characters on my I2C LCD

hi i have a problem with characters on my lcd being left behind when the day of the week changes.
my lcd is a 20x4 and it is laid out like this:

06/05/2017 Monday
04:13:40AM
Humidity: 51.70%
Temperature: 78.08°F

so every week after Wednesday it will look like this
Thursdayy, Fridayayy and so on.

I don't know a lot of programing so any help is appreciated.

for the clock i am using this library GitHub - jarzebski/Arduino-DS3231: DS3231 Real-Time-Clock

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
#include "DHT.h"
#define DHTPIN 5     // what digital pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

const int chipSelect = 4;
DHT dht(DHTPIN, DHTTYPE);
DS3231 clock;
RTCDateTime dt;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte ozel[8] = {
  B01000,
  B10100,
  B01000,
  B00111,
  B00100,
  B00111,
  B00100,
  B00100,
};

void setup() {
  dht.begin();
  Wire.begin();
  lcd.begin(20, 4);
  lcd.backlight();
  lcd.createChar(1, ozel);
  clock.begin();

  if (!SD.begin(chipSelect)) {
    return;
  }
}

void loop()
{
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    return;
  }
  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  dt = clock.getDateTime();

  lcd.setCursor(0, 0);
  lcd.print(clock.dateFormat("m/d/Y l", dt));
  lcd.setCursor(0, 1);
  lcd.print(clock.dateFormat("h:i:sA", dt));
  lcd.setCursor(0, 2);
  lcd.print(F("Humidity: "));
  lcd.print(h);
  lcd.print(F("%"));
  lcd.setCursor(0, 3);
  lcd.print(F("Temperature: "));
  lcd.print(f);
  lcd.write(1);

  if (dataFile) {
    dataFile.print(clock.dateFormat("m/d/Y l h:i:sA", dt));
    dataFile.print(" ");
    dataFile.print(F("Humidity: "));
    dataFile.print(h);
    dataFile.print(F("%"));
    dataFile.print(" ");
    dataFile.print(F("Temperature: "));
    dataFile.print(f);
    dataFile.print(F("°F"));
    dataFile.println();
    delay(15);
    dataFile.close();
  }
}

clear()

If you want to clear a single line first, position the cursor at the beginning of the line and write 20 spaces.

Next you can position the cursor at the beginning of the line and write new text (if needed).

The longest day name is "Wednesday", with 9 letters. The others are all shorter, down to "Monday" and "Friday" at 6 letters each.

If you print the day name followed by three spaces, all the letters in the longest name will be overwritten, regardless of the name being printed or the name be overwritten.

What happens when you print 23 characters on one line of a 20 characters per line LCD ? Do the extra characters just disappear ?

07/06/2017^Wednesday^^^

Where ^ represents a space.

@UKHeliBob @PaulS

if you exceed the 20 characters on line 1 they get truncated to line 3

Another simple solution is to position the cursor where you will print the day, print 9 spaces, reposition the cursor and print the day.

an easier/prettier way (and OP doesn't appear resource confined) is to use: snprintf() and guarantee that he always gets his 20 chars formatted properly...

yeah he has to do some float to int machinations, but worth it when you see the final code...

@UKHeliBob

from @sterretje suggestion i did this

lcd.setCursor(11, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l", dt));

and that does work but the day of the week flashes every time the lcd updates.

i did have an idea i just don't know how to do it or if it will work

what about some kind of if statement that checks the day of the week and than it will use 1 of the lines below

clock.dateFormat("l", dt) == Monday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l   ", dt));

clock.dateFormat("l", dt) == Tuesday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l  ", dt));

clock.dateFormat("l", dt) == Wednesday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l", dt));

clock.dateFormat("l", dt) == Thursday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l ", dt));

clock.dateFormat("l", dt) == Friday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l   ", dt));

clock.dateFormat("l", dt) == Saturday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l ", dt));

clock.dateFormat("l", dt) == Sunday
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y l   ", dt));

@BulldogLowell

that sounds good I looked at your link and i have no idea how to do that :confused:

all of the code so far is cobbled together from example code in my attempts to learn to program

The LCD will always flash when you write to it. It flashes more, the more you write to it. So no matter what back end approach you use, it is better to write each LCD character only once.

If you want to calculate the number of spaces required, you could use strlen() to get the length of clock.dateFormat("l ", dt).

the day of the week flashes every time the lcd updates.

So don't update the whole LCD but only the data that changes.

Ok so I'm going with this now

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
#include "DHT.h"
#define DHTPIN 5     // what digital pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

const int chipSelect = 4;
DHT dht(DHTPIN, DHTTYPE);
DS3231 clock;
RTCDateTime dt;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte ozel[8] = {
  B01000,
  B10100,
  B01000,
  B00111,
  B00100,
  B00111,
  B00100,
  B00100,
};

void setup() {
  dht.begin();
  Wire.begin();
  lcd.begin(20, 4);
  lcd.backlight();
  lcd.createChar(1, ozel);
  clock.begin();

  if (!SD.begin(chipSelect)) {
    return;
  }
}

void loop()
{
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    return;
  }
  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  dt = clock.getDateTime();

lcd.setCursor(0, 0);
lcd.print(clock.dateFormat("m/d/Y ", dt));
if (clock.dateFormat("l", dt) == "Monday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));
}
else if (clock.dateFormat("l", dt) == "Tuesday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l  ", dt));
}
else if (clock.dateFormat("l", dt) == "Wednesday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l", dt));
}
else if (clock.dateFormat("l", dt) == "Thursday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l ", dt));
}
else if (clock.dateFormat("l", dt) == "Friday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));;
}
else if (clock.dateFormat("l", dt) == "Saturday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));
}
else{
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));
}
lcd.setCursor(0, 1);
  lcd.print(clock.dateFormat("h:i:sA", dt));
  lcd.setCursor(0, 2);
  lcd.print(F("Humidity: "));
  lcd.print(h);
  lcd.print(F("%"));
  lcd.setCursor(0, 3);
  lcd.print(F("Temperature: "));
  lcd.print(f);
  lcd.write(1);

  if (dataFile) {
    dataFile.print(clock.dateFormat("m/d/Y l h:i:sA", dt));
    dataFile.print(" ");
    dataFile.print(F("Humidity: "));
    dataFile.print(h);
    dataFile.print(F("%"));
    dataFile.print(" ");
    dataFile.print(F("Temperature: "));
    dataFile.print(f);
    dataFile.print(F("°F"));
    dataFile.println();
    delay(15);
    dataFile.close();
  }
}

I know it is ugly but it works and is the best i can do

@BulldogLowell

i looked into using snprintf() and i have no idea how to use it if you have some time can you post an example of how to use it in this situation.

Thx for the help everyone

So, you go through all these machinations in order to fill spaces when you print the day:

if (clock.dateFormat("l", dt) == "Monday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));
}
else if (clock.dateFormat("l", dt) == "Tuesday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l  ", dt));
}
else if (clock.dateFormat("l", dt) == "Wednesday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l", dt));
}
else if (clock.dateFormat("l", dt) == "Thursday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l ", dt));
}
else if (clock.dateFormat("l", dt) == "Friday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));;
}
else if (clock.dateFormat("l", dt) == "Saturday"){
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));
}
else{
  lcd.setCursor(11, 0);
    lcd.print(clock.dateFormat("l   ", dt));
}

instead, you could do all of this in four lines:

char dispBuffer[21] = ""; // create 'empty C string capable of holding 20 characters
snprintf(dispBuffer, sizeof(dispBuffer), "%10s", clock.dateFormat("l", dt)); // %20s -> says pad the string to always fill with spaces to a width of 20
lcd.setCursor(11, 0);
lcd.print(dispBuffer);

spend some time looking at sprintf(), snprintf() and the C Format Specifiers

I'm trying to figure out how your code can possibly work. The dateFormat method returns a pointer to an character array, not a String (capital S). So you should use strcmp() and not == in e.g

if (clock.dateFormat("l", dt) == "Monday")

To use sprintf, the below should work:

char buffer[21];
sprintf(buffer, "%10s", clock.dateFormat("l", dt));
lcd.print(buffer);