Cursor won't go down to Line 1

I have a 16x2 LCD display, I am making a simple morse code generator / decoder project, and I added a counter to determine when 16 letters have been entered. The issue is depending on the letter I type the display will not move the cursor down (and even produces a weird error where it looks like a character is seemingly inserted into the 16th row ontop of the character that is already displayed).

I've noticed that when my 16th letter is an S it will work, as will anything above the char(S), anything below it will also work, if i keep inputting and the characters eventually overflow to the next line naturally.

Any help as to why this is happening would be greatly appreciated!

On a side note, anytime the buffer overflows with DITS or DAHs and Char goes above the numeric characters it overflows to 124 ( | ), any ideas on why it stops here? I already have a plan of action to fix this by determining if the value overflows a numerical char that represents a character it will erase the buffer and will not write to the LCD screen waiting for a valid character to write into the current cursor position.

#include <LiquidCrystal.h> // Bibloteca para tela LCD
LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Pinos da arduino ligados respectivamente ao (rs, enable, d4, d5, d6, d7).

int botao = 8, piezo = 9;

bool ultimoEstadobotao = false; // Ultimo estado do botao.
int botaoEstado = 0; // Estado atual do botao.
int inicioPressionado = 0; // Momento em que o botao foi acionado.
int fimPressionado = 0; // Momento em que o botao foi liberado.
int tempoSegurado = 0; // Quanto tempo o botao foi acionado.
int tempoParado = 0; // Quanto tempo o botao esta parado.

int numeroLetras = 0; // Contador que armazena a quantidade de letras que já foram digitadas.
String buffer = ""; // Buffer para armazenar os Dits e Dats que compoem uma letra.


void setup ()
{
  // Inicializa a interface da tela LCD e define as dimensoes da tela (quantidade de colunas e linhas respectivamente).
  lcd.begin(16, 2);
  pinMode (botao, INPUT);
  Serial.begin(9600);
}

void loop() 
{
  // Leia o input do botao
  botaoEstado = digitalRead(botao);

  if (botaoEstado == LOW) 
  {
    // Letra
    if ((millis() - fimPressionado) % 65536 > 500) 
    {
      // Se o buffer tiver algum valor printa a letra.
      if (buffer != "") 
      { 
        Serial.println(retornarBuffer());
        limpaBuffer();
        numeroLetras++;
        ultimoEstadobotao = true;
      }
    }

    // Palavra
    if ((millis() - fimPressionado) % 65536 > 1350)
    {
      if (ultimoEstadobotao == true) 
      {
        Serial.println("Espaço");
        ultimoEstadobotao = false;
      }
    }
  }

  // Estado do botao foi alterado
  else if (botaoEstado == HIGH ) 
  {
    inicioPressionado = millis();

    atualizarEstado();
  }

  moverCursor();

}

void moverCursor() 
{
  // Quando 16 letras forem escritas move o cursor da tela LCD para a linha de baixo, adicione um ao contador de letras para que o Loop n seja infinito
  if(numeroLetras == 15)
  {                          
    Serial.println("LCD configurada para linha 1"); 
    numeroLetras++;
    lcd.setCursor(0, 1);
  }
}

// Limpa o Buffer
void limpaBuffer() 
{
  buffer = "";
}

// Aplica o valor do buffer a função do codigo morso para que ele seja comparado a lista existente.
String retornarBuffer() 
{
  return morseParaChar(buffer);
}

void atualizarEstado() 
{
  // O botao foi apertado.
  while (digitalRead(botao) == HIGH)
  {
    fimPressionado = millis();
  }

  // O botao foi liberado
  tempoSegurado = fimPressionado - inicioPressionado;

  // Se o botao foi segurado por menos de 300 millisegundos, adicione um DIT (.) ao buffer.
  if (tempoSegurado < 300) 
  {
    tone(9, 675, 200);
    Serial.println("DIT");
    buffer += ".";
  }

  // Se o botao foi segurado por mais de 300 millisegundos, adicione um DAH (-) ao buffer.
  else if (tempoSegurado >= 300)
  {
    tone(9, 675, 500);
    Serial.println("DAH");
    buffer += "-";
  }
}

// Define uma lista de strings que contem todo o alfabeto morse, relacionado a sua posição dentro da lista (seu indice)
String morseParaChar(const String& morse) 
{
  static String letras[26] = 
  {".-", "-...", "-.-.", "-..", ".",
  "..-.", "--.", "....", "..", ".---",
  "-.-", ".-..", "--", "-.", "---",
  ".--.", "--.-", ".-.", "...", "-",
  "..-", "...-", ".--", "-..-",
  "-.--", "--.."
  };

// Um for loop que compara o buffer (morse) com o indice da lista especifica e adiciona ele ao valor do char, assim o A seria indice 0 + 65 = char(65)
// que é o char A, o 66 seria o B e assim em diante.
  for (int k = 0; k < sizeof(letras); k++)
   {

    if (letras[k] == morse) 
    {
      lcd.print((char) (k + 65));
      return ((String) (k + 65));
    }
  }
}

The number of letters that you count begins at zero, so your count is 15 when the line is full, NOT 16.

I fixed the counter now I need to test it out, even so after typing one more letter it should still reposition the cursor and it doesn't so I don't believe thats the root cause of this, but good catch

Remembering that if the 16th letter is an S or above, the cursor repositions properly, if the 16th letter is anything else it will bug out like I described.

Then start to put in serial.Print() code to track the values and where the your logic is correct or fails, then you can understand what is wrong. So much better than just guessing!

What Arduino are you using? ... often not a good idea to use GPIO pin 1.

This is used for serial communication.

Try a different pin.

If you can not figure out what is going on (and the behavior of the cursor advance dedpending on the actual letter certainly leaves me scratching my head) you can try the hd44780.h lcd library by Bill Perry. It is available through the library manager, and it supports line wrap.

The hd44780.h can work with your display and any wiring arrangement you choose to avoid pin1. You will need to use the Pin I/O class of the library with your display, and here's the library example to demonstrate line wrap for your display wiring.

// vi:ts=4
// ----------------------------------------------------------------------------
// LineWrap - simple demonstration of automatic linewrap functionality
// Created by Bill Perry 2017-05-10
// bperrybap@opensource.billsworld.billandterrie.com
//
// This example code is unlicensed and is released into the public domain
// ----------------------------------------------------------------------------
//
// This sketch is for LCDs that are directly controlled with Arduino pins.
//
// Sketch demonstrates hd44780 library automatic line wrapping functionality.
//
// Background:
// hd44780 LCDs do not use linear continuous memory for the characters
// on the lines on the display.
// This means that simply sending continuous characters to the
// display will not fill lines and wrap appropriately as might be expected.
// The hd44780 library solves this issue by adding a line wrapping capability
// in s/w that can be enabled & disabled.
// This allows the host to send characters to the display continuously and they
// will wrap to the next lower line when the end of the visible line has been
// reached. When on the bottom line it will wrap back to the top line.
// 
// (Configure LCD_COLS & LCD_ROWS if desired/needed)
// Expected behavior of the sketch:
// - display a banner announcing the test.
// - print the configured LCD geometry 
// - print a long text string to demostrate automatic line wrapping 
// - print lots of characters (slowly) to show how the full wrapping works.
// (loop)
//
// If initialization of the LCD fails and the arduino supports a built in LED,
// the sketch will simply blink the built in LED with the initalization error
// code.
//
// Special note for certain 16x1 displays:
// Some 16x1 displays are actually a 8x2 display that have both lines on
// a single line on the display.
// If you have one of these displays, simply set the geometry to 8x2 instead
// of 16x1. 
// In normal sketches, lineWrap() mode will allow this type of display to
// properly function as a 16x1 display in that it will allow printing up to
// 16 characters on the display without having to manually set the cursor
// position to print the right characters on the half of the display.
// However, when using this 8x2 display as a 16x1 display, 
// scrollDisplayLeft() and scrollDisplayRight() will not work as intended.
// They will shift the two halves of the display rather than the entire display.
// This is because the hd44780 chip is doing the shift and chip is hard coded
// internally for two lines.
//
// ----------------------------------------------------------------------------
// While not all hd44780 use the same pinout, here is the one that most use:
// pin 1 is the pin closest to the edge of the PCB
//  1 - LCD gnd
//  2 - VCC (5v)
//  3 - Vo Contrast Voltage
//  4 - RS Register Select (rs)
//  5 - Read/Write
//  6 - Enable (en)
//  7 - Data 0 (db0) ----
//  8 - Data 1 (db1)     |-------- Not used in 4 bit mode
//  9 - Data 2 (db2)     |
// 10 - Data 3 (db3) ----
// 11 - Data 4 (db4)
// 12 - Data 5 (db5)
// 13 - Data 6 (db6)
// 14 - Data 7 (db7)
// 15 - Backlight Anode (+5v)
// 16 - Backlight Cathode (Gnd)
// ----------------------------------------------------------------------------

#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h> // Arduino pin i/o class header

// declare Arduino pins used for LCD functions
// and the lcd object

// Note: this can be with or without backlight control:

// without backlight control:
// note that ESP8266 based arduinos must use the Dn defines rather than
// raw pin numbers.
#if defined (ARDUINO_ARCH_ESP8266)
const int rs=D8, en=D9, db4=D4, db5=D5, db6=D6, db7=D7; // esp8266 Lolin/Wemos D1 R1 (uno form factor)
#elif defined(ARDUINO_ARCH_ESP32)
// note: GPIO12 needs a pulldown resistor
const int rs=12, en=13, db4=17, db5=16, db6=27, db7=14; // esp32 espduino32 D1 R32 (uno form factor)
#else
const int rs=8, en=9, db4=4, db5=5, db6=6, db7=7;       // for all other devices
#endif
hd44780_pinIO lcd(rs, en, db4, db5, db6, db7);

//with backlight control:
//	backlight control requires two additional parameters
//	- an additional pin to control the backlight
//	- backlight active level which tells the library the level
//		needed to turn on the backlight.
//		note: If the backlight control pin supports PWM, dimming can be done
//			using setBacklight(dimvalue);
//
//	WARNING: some lcd keypads have a broken backlight circuit
//		If you have a lcd keypad, it is recommended that you first run the
//		LCDKeypadCheck sketch to verify that the backlight circuitry
//		is ok before enabling backlight control.
//		However, the hd44780_PinIO class will autodetect the issue and
//		work around it in s/w. If the backlight circuitry is broken,
//		dimming will not be possible even if the backlight pin supports PWM.
//
#if defined (ARDUINO_ARCH_ESP8266)
// esp8266 Lolin/Wemos D1 R1 (uno form factor)
//const int rs=D8, en=D9, db4=D4, db5=D5, db6=D6, db7=D7, bl=D10, blLevel=HIGH;
#elif defined(ARDUINO_ARCH_ESP32)
// esp32 espduino32 D1 R32 (uno form factor)
// note: GPIO12 needs a pulldown resistor
//       Dimming will not work on esp32 as it does not have analogWrite()
//const int rs=12, en=13, db4=17, db5=16, db6=27, db7=14, bl=5, blLevel=HIGH;
#else
//const int rs=8, en=9, db4=4, db5=5, db6=6, db7=7, bl=10, blLevel=HIGH;
#endif
//hd44780_pinIO lcd(rs, en, db4, db5, db6, db7, bl, blLevel);

// LCD geometry
// while 16x2 will work on most displays even if the geometry is different,
// for actual wrap testing of a particular LCD it is best to use the correct
// geometry.
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

void setup()
{
int status;

	// initialize LCD with number of columns and rows: 
	// hd44780 returns a status from begin() that can be used
	// to determine if initalization failed.
	// the actual status codes are defined in <hd44780.h>
	status = lcd.begin(LCD_COLS, LCD_ROWS);
	if(status) // non zero status means it was unsuccesful
	{
		// begin() failed so blink error code using the onboard LED if possible
		hd44780::fatalError(status); // does not return
	}

	// turn on automatic line wrapping
	// which automatically wraps lines to the next lower line and wraps back
	// to the top when at the bottom line
	// NOTE: 
	// noLineWrap() can be used to disable automatic line wrapping.
	// _write() can be called instead of write() to send data bytes
	// to the display bypassing any special character or line wrap processing.
	lcd.lineWrap();

}

void loop()
{
	lcd.clear();
	lcd.print("WrapTest"); 
	delay(2000);
	lcd.clear();

	//print the configured LCD geometry
	lcd.print(LCD_COLS);
	lcd.print("x");
	lcd.print(LCD_ROWS);
	delay(3000);
	lcd.clear();

	// print a long text string
	// without line wrapping enabled, the text would not wrap properly
	// to the next line.

	if(LCD_COLS == 8)
		lcd.print("A long text line");
	else
		lcd.print("This is a very long line of text");
	delay(3000);

	lcd.clear();

	// now print 2 full displays worth of characters to show
	// the full wrapping.

	lcd.cursor(); // turn on cursor so you can see where it is

	char c = '0'; // start at the character for the number zero
	for(int i = 2*LCD_COLS*LCD_ROWS; i; i--)
	{
		lcd.print(c++);
		delay(200); // slow things down to watch the printing & wrapping

		if(c > 0x7e) // wrap back to beginning of printable ASCII chars
			c = '!'; 
	}
	delay(3000);
	lcd.noCursor(); // turn off cursor
}

Hey guys, thanks everyone for the feedback

@ Paul I'd just like to clarify my code was full of serial.Print() to track each step of the code, including the counters and numerical / char values stored in the buffer at many given steps, I removed this as I am about to present my code for the project.
The moveCursor functionality I added was a bit of an extra as I only really need to print to one line of the LCD.

@red_car I will try and change the pins, I noticed some funny things happening with the circuit at times and thats probably has to do with me using the 1pin! thanks for the suggestion I will get back to you guys once I debug this and figure out what happened (right now my protoboard is holding an RS flip flop circuit I have due tomorrow so I can't set the circuit back up just yet)

@cattledog Thanks for the suggestion of using a different library to control the LCD screen, I'll give that a shot if I cannot debug using the standard library!

Thanks everyone for the responses, I will update this topic as soon as I can try some of these and figure out whats going on in case anyone else has this issue in the future!

Just a heads up @red_car was spot on, do NOT use the GPIO pin 1 (TX line on my Arduino UNO)
I changed the pins and everything is working as expected now from a cursor standpoint.

The mysterious 124 overflow is still happening though (I believe whenever an order of DITS and DAHS that is not stored in the letras array is given it defaults to 124) I will investigate further with some Serial.printIn to figure out why this happens and edit this response once I figure that out.

Thanks everyone for your assistance, much appreciated!

I believe this line is a potential source of trouble.

  for (int k = 0; k < sizeof(letras); k++)

In this instance sizeof will return the size in bytes (156) of the entire array, not 26 as you are expecting.