Bluetooth text communication to non-I2C lcd on both lines (Line wrapping?)

Hey, this is my first time doing this, please be gentle. I only say this because there are some condescending unhelpful assholes floating around coding forums from what i've seen.
Anyway, please hear me out, i'll keep it as short as possible:

This is a program that allows me to communicate with a hc05 bluetooth serial terminal app on my phone (and physical module) and write anything I type on the lcd. (The following program works):

#include <LiquidCrystal.h>

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 =2;
LiquidCrystal lcd(rs,en, d4, d5,d6, d7);
void setup() 
{
  //DONT CHANGE!!!!!!!!!!!
  //16 rows 2 columns
  lcd.begin(16,2);
  Serial.begin(9600);
  
} 

void loop()
{
  if(Serial.available())
  {
    delay(100);
    lcd.clear();
    while(Serial.available()>0) 
    {
      lcd.write(Serial.read());
    }
    
  }
}

I'm trying to modify this program so that I can write on both lines.In other words, if you type the alphabet, you'll see the first line ends with 'p' and the next line begins with 'q'. (I think the second line is known as (0,1)). So I wrote the following program to help me do this, and I didn't get any errors, but the lcd was totally blank after I uploaded the code and started typing. I DO NOT have an I2C (module or LCD?), which I've heard might make this kind of thing easier. My exact LCD is a 16x2,16 pin, QAPASS 1602A module and I've heard there is a thing about it's cg (or some other kind of) RAM "addresses" which makes it so that the second row might be 0,1, but also goes from 40, 41 , 42 .. 49, 4A, 4B..
I wrote the whole thing in a comment in the following code, but the rest of the comments are kind of nonsense, so you might want to ignore those.
Thank you so much for giving your time into helping me! I'll reply with more details if you need them.

So this is my problem-program (again, no errors, just a blank lcd screen):

//#include <LiquidCrystal_I2C.h>
//lcd.blink makes the cursor blink
//lcd.cursor or lcd.nocursor

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 =2;
LiquidCrystal lcd(rs,en, d4, d5,d6, d7);
String thing = (Serial.readString());
char* k = (Serial.read());
// []^^^^^
// pretty basic, but how do you do the whole char array for a string? is this right?
// char um[] = { '00', '01', '02', '03','04','05','06','07','08','09', '0A','0B','0C','0D','0E','0F'};
// char umm[] = { '40', '41', '42', '43','44','45','46','47','48','49', '4A','4B','4C','4D','4E','4F'};
//the goal is to assign these to my 0 - 16 , 17  -length() for loops i guess? ^^^
//abcdefghijklmnop qrstuvwxyz  
// cut off at 10 to 16
//try changning to const int?
void setup() 
{
  //16 rows 2 columns
  lcd.begin(16,2);
  Serial.begin(9600);
  
}
void loop()
{
  if(Serial.available())
  {
    delay(100);
    lcd.clear();
    while(Serial.available()>0) 
    {
      //lcd.write(Serial.read());
      // ^^okay seriously consider adding this back
      if((thing.length()) > 16)
      {
        //______________________________________
        //char k[] = serial.read             |
        //string thing = serial.readstring      |
        //______________________________________|
        //lcd.clear();
        //^^ maybe put this in?
          for(int j =0; j<=16;j++)
          {
             //(set cursor 0,0?)
            lcd.write(k[j]); 
            //lets say its 21 characters
          }
          for(int o = 17; o< ((thing.length())-(16)); o++)
          {
            //i guess not 40
             lcd.setCursor(0,1);
             lcd.write(k[o]);
          }
            
        }
        
        
      }
   }
    
  }

If i may suggest the hd44780 library for LCDs. Uding that library you can enable automatic line wrapping.

Install the hd44780 library. The library is available in the Library Manager. Go to Library Manager (in the IDE menus, Sketch, Include Libraries, Manage Libraries) and in the Topics dropdown choose Display and in the Filter your search box enter hd44780. Select and install the hd44780 library by Bill Perry.

The class that you should use is the hd44780_pinIO class. That class is written for LCDs wired parallel and 4 or 8 bits (not I2C). In the examples for the hd44780_pinIO class is an example showing how to enable and use line wrapping.

char um[] = { '00', '01', '02', '03','04','05',

Single quotes for single characters. 00, for instance, is not a single character. If you enable warnings in the IDE File, Preferences, Compiler Warnings, All you would see that the compiler warns you of that.

You may also be interested in Robin2's serial input basics tutorial.

chubbs1938,
Whether the host talks to the hd44780 lcd using direct pin control or over i2c using an 2c backpack, it doesn't much matter.
The main sketch code will be the same as both types of devices have libraries that offer the same API.
Identical if using the hd44780 library.
The only difference is the header files included, and the lcd object declaration and constructor.

The lcd library should handle all the DDRAM addressing for you when you use setCursor() so there is no need to worry about the discontinuous memory locations for the lcd lines.

What isn't handled automatically is line wrapping as it is not handled by the lcd itself and most libraries don't handle it in the library.
But the hd44780 library does.

I would recommend using the hd44780 library.
Assuming your serial data doesn't have line control characters ( or ) that need to be processed in the message,
it is as simple as enabling linewrapping in the hd44780 library.
One enabled, the library will handle line wrapping for you, so if you send more characters than fit on a line, the library will wrap them to the next line. If on the bottom line, it will wrap back to the top line.

--- bill

Hey guys, thanks for the advice. It worked! Just one last question though: How do you make it so that if the message takes up more than 32 characters, it lcd.clears (or ignores it if you know how to do that) ?

#include <LiquidCrystal.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 =2;
//LiquidCrystal lcd(rs,en, d4, d5,d6, d7);
hd44780_pinIO lcd(rs,en, d4, d5,d6, d7);
#if defined (ARDUINO_ARCH_ESP8266)
#else
#endif
//String thing= Serial.readString();  ___________________________________________ heres the problem (implemented in the void loop section             ____________________________________
//I tried both the readString and read, but they both gave the same result of a blank screen
char* k = (Serial.read());
void setup() 
{
  int status;

  //16 rows 2 columns
  status = lcd.begin(16,2);
  
  if(status)
  {
    hd44780::fatalError(status);
  }
  
  Serial.begin(9600);
  lcd.lineWrap();
  
} 

void loop()
{
  
  if(Serial.available())
  {
    delay(100);
    lcd.clear();
    while(Serial.available()>0) 
    {
      
      //lcd.write(Serial.read());
      
      if((k) > 32)
      {
      // ^^ here i put k ( k is a char array equal to Serial.read) but i also tried thing.length() (represents readString called thing)
        lcd.clear();
        //lcd.print("haha u thot try again");
      }
      else
      {
        lcd.write(Serial.read());
      }
      
    }
    
  }
}

I tried adding this code which I thought had no chance of failing (obviously read and readstring aren't what I thought they were, so that's probably where the problem is), but like always, i'm wrong, and the lcd gave me a blank screen and no response after powering on and connecting.

Thanks for your help so far! I spent a day on this and ignored this library because I thought it was only for that type of LCD!

Here is an example that does what i think that you want. It uses a modified version of example 2 of Robin2's serial input basics. I read in the entire string and then, based on the number of characters received, clear the LCD or print the incoming data. Make sure to send a newline ('\n' or enter) character as the last character from the Bluetooth. Are you using software serial for the Bluetooth module?

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

const int rs = 12, en = 11, db4 = 5, db5 = 4, db6 = 3, db7 = 2;

hd44780_pinIO lcd(rs, en, db4, db5, db6, db7);

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

const byte numChars = 64;  // room for lots of incoming characters w/o overflow the buffer
char receivedChars[numChars];
byte length = 0;
boolean newData = false;

void setup()
{
   Serial.begin(115200);
   lcd.begin(LCD_COLS, LCD_ROWS);
   lcd.print("Hello, World!");
   lcd.lineWrap();
}

void loop()
{
   recvWithEndMarker();
   if (newData == true)
   {
      if (length > 32)
      {
         lcd.clear();
      }
      else
      {
         lcd.clear();
         lcd.print(receivedChars);
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();
      if (rc == '\r')
      {
         return;
      }
      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         length = ndx;
         ndx = 0;
         newData = true;
      }
   }
}

Hey again.

I've tried combining the code together again, but I got a blank screen an no reponse like the other 2 times.
Here's how I combined the code:

#include <LiquidCrystal.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 =2;
//LiquidCrystal lcd(rs,en, d4, d5,d6, d7);
hd44780_pinIO lcd(rs,en, d4, d5,d6, d7);
//String thing= Serial.readString();
//char* k = (Serial.read());
const byte numChars = 64;  // room for lots of incoming characters w/o overflow the buffer
char receivedChars[numChars];
byte length = 0;
boolean newData = false;
void setup() 
{
  int status;
  lcd.begin(16,2);
  Serial.begin(9600);
  lcd.lineWrap();
  
} 

void loop()
{
  /*
  previous working code:
  if(Serial.available())
  {
    delay(100);
    lcd.clear();
    while(Serial.available()>0) 
    {
      lcd.write(Serial.read());
    }
    */

    recvWithEndMarker();
   if (newData == true)
   {
      if (length > 32)
      {
         lcd.clear();
      }
      else
      {
         lcd.clear();
         lcd.print(receivedChars);
      }
      newData = false;
   }
    
    
  }
  void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (Serial.available() > 0 && newData == false)
   {
      rc = Serial.read();
      if (rc == '\r')
      {
         return;
      }
      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         length = ndx;
         ndx = 0;
         newData = true;
      }
   }
}

Thanks again so much for your help. I don't think I would've ever figured this out on my own

Why combining codes? Did not the code that I posted do what you want? That code is tested on my Uno with 1602 LCD. Works as described.

The code is set up so that you can enter characters via the serial monitor. How are you sending characters?

Is your serial monitor baud rate set to 115200? My code had 115200, change it to 9600 in Serial.begin() if that is what you prefer. With my unmodified code, do you see "Hello, World!" at startup in the LCD?

I'm sending it from my android in a terminal in an app called "Arduino bluetooth controller". I've also used the "Arduino BlueControl" and the "Bluetooth Terminal HC-05" apps. Not the serial monitor in arduino. Sorry, I didn't realize what you were talking about until now. I wouldn't imagine that it should be too different because I've been able to send text (with line wrapping) via my android in the other program you gave me.
I couldn't find any app that lets you adjust the buad rate of arduino bluetooth devices, but I changed your program and adjusted it to 9600 after seeing 115200 wasn't working, but that didn't work either. Still just the blank screen. Any other programs that you know of that might accomplish the same thing a different way (Without having to interact specifically through the arduino software serial monitor)?

Serial is serial. If it works with the serial monitor inputting characters it should work the same if characters were coming from Bluetooth.

Did you see this:

Make sure to send a newline ('\n' or enter) character as the last character from the Bluetooth.

With my unmodified code, do you see "Hello, World!" at startup in the LCD? If you do not see the hello world message on the LCD something else is going on. The LCD message has nothing to do with serial.

What Arduino are you using?

I set up a Bluetooth module and modified the code that I posted before to use a software serial port for the Bluetooth. Note the pins that my Bluetooth module is connected to (pins 7 [to bt TX] and 8 [to bt RX]). I sent test messages from Serial Bluetooth Terminal on my tablet. Works as advertised. If this does not work for you I don't know what else to do. I use software serial because I can use hardware serial (USB) for program upload and to monitor program flow and variable values. Serial is a valuable debugging tool.

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

const int rs = 12, en = 11, db4 = 5, db5 = 4, db6 = 3, db7 = 2;

hd44780_pinIO lcd(rs, en, db4, db5, db6, db7);
SoftwareSerial bt(7,8);

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

const byte numChars = 64;  // room for lots of incoming characters w/o overflow the buffer
char receivedChars[numChars];
byte length = 0;
boolean newData = false;

void setup()
{
   Serial.begin(9600);
   bt.begin(9600);
   lcd.begin(LCD_COLS, LCD_ROWS);
   lcd.print("Hello, World!");
   lcd.lineWrap();
}

void loop()
{
   recvWithEndMarker();
   if (newData == true)
   {
      if (length > 32)
      {
         lcd.clear();
      }
      else
      {
         lcd.clear();
         lcd.print(receivedChars);
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (bt.available() > 0 && newData == false)
   {
      rc = bt.read();
      Serial.print(rc);
      if (rc == '\r')
      {
         return;
      }
      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         length = ndx;
         ndx = 0;
         newData = true;
      }
   }
}

This is a program that allows me to communicate with a hc05 bluetooth serial terminal app on my phone (and physical module) and write anything I type on the lcd, and it's complete with line wrapping thanks to the wonderful hd44780 library. (The following program works):

#include <LiquidCrystal.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 =2;
//LiquidCrystal lcd(rs,en, d4, d5,d6, d7);
hd44780_pinIO lcd(rs,en, d4, d5,d6, d7);

//String thing= Serial.readString();
//char* k = (Serial.read());
void setup() 
{
  
  
  lcd.begin(16,2);
  
  
  
  Serial.begin(9600);
  lcd.lineWrap();
} 

void loop()
{
  
  if(Serial.available())
  {
    delay(100);
    lcd.clear();
    while(Serial.available()>0) 
    {
      
      lcd.write(Serial.read());
    }
   
  }
}

While this code helped me to do line wrapping, I have yet to be able to modify it so that it does what I want successfully. I want to get it to where it clears the screen after the whole screen is filled with characters without ruining the line wrapping. If i'm misunderstanding what line wrapping means, then what I mean to say is the code can't make it so that the cursor doesn't go to the next row after the first 16 characters are typed. My exact LCD is a 16x2,16 pin, QAPASS 1602A module if that helps. Again, I'm sending these all from my phone in a terminal in an app called "Arduino bluetooth controller". I've also used the "Arduino BlueControl" and the "Bluetooth Terminal HC-05" apps.

Thank you!

As a disclaimer, I've tried the following code but was met with a blank LCD screen when I tried sending messages (blank, but with a working back light and everything)

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

const int rs = 12, en = 11, db4 = 5, db5 = 4, db6 = 3, db7 = 2;

hd44780_pinIO lcd(rs, en, db4, db5, db6, db7);
SoftwareSerial bt(7,8);

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

const byte numChars = 64;  // room for lots of incoming characters w/o overflow the buffer
char receivedChars[numChars];
byte length = 0;
boolean newData = false;

void setup()
{
   Serial.begin(9600);
   bt.begin(9600);
   lcd.begin(LCD_COLS, LCD_ROWS);
   lcd.print("Hello, World!");
   lcd.lineWrap();
}

void loop()
{
   recvWithEndMarker();
   if (newData == true)
   {
      if (length > 32)
      {
         lcd.clear();
      }
      else
      {
         lcd.clear();
         lcd.print(receivedChars);
      }
      newData = false;
   }
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (bt.available() > 0 && newData == false)
   {
      rc = bt.read();
      Serial.print(rc);
      if (rc == '\r')
      {
         return;
      }
      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         length = ndx;
         ndx = 0;
         newData = true;
      }
   }
}

I've also tried replacing all of the bt.reads, bt.availables, etc. with Serial.read. . and also imported the LiquidCrystal library but still the blank LCD.

Thanks again

Sounds like you are doing all sorts of totally random things ("also imported the LiquidCrystal library". Just why would you do that? :roll_eyes: ).

The 1602 module is clearly entirely inappropriate for use as a raw text display. It is not a "VDU". It is useful for displaying specific crafted messages and strictly defined data fields.

You need to determine what it is you actually want to do, and choose suitable hardware. Do you want to print incoming text data? OK, get a display which will accommodate the amount of text you anticipate, and get the hardware that will dive that display. Probably a Raspberry Pi and large TFT screen by the sounds of it. The Arduino is very useful, but not the "go-to" for any random application.

I've had someone introduce to me ways that they would do it, It just didn't work for me. It's probably not the most ideal for 1602, but it doesn't seem like that impossible of a task, especially since you can wrap lines and even insert customizable characters.
I would be on my way if I just knew how to reference the cursor position at any given point in time. It has cgram, right? Bytes for each char? The display addresses? It has the lcd.clear function,right? Do for loops exist?

You can't possibly tell me there's no way this task can be accomplished. I just don't know the terminology or the specific way I can access that information for specifically my 1602.

I have read your description of what you want to do 5-6 times and I still don't understand what you are wanting to do.
If I look at and take what you said literally: you stated you wanted to clear the screen after filling it (displaying 32 characters on this display) and that is it. Which would imply that you never expect to show anything else on the display.
I doubt that is what you wanting.

And I really have no clue what you talking about in post #3.
The library includes lots of documentation including descriptions of all the API functions and links to hd44780 datasheets.

Can you fully describe what you are wanting to do?

--- bill

Yeah, you're right. I just wanted for it to be able to print messages that are 32 characters max in length (if they aren't then the lcd will clear the screen). If it's possible, maybe I'd even want it to just ignore the last 4 characters (if a message is 36 characters long, for example,) and just print the first 32 characters. Otherwise, everything would just work the same way.
Sorry if i'm not being clear, I'm doing my best here and I appreciate your patience. I'm just trying to keep it short so my program is more likely to work with other peoples code's.
I also thought other people using the hd44780 library might've had the same problem. (Naturally when you interact with a screen by texting, it doesn't just keep the same text and just start writing over it if you're writing too much).
Thanks again

wait, isn't this the same topic as your other thread?
https://forum.arduino.cc/index.php?topic=692914.0
Did what GroundFungus propose not work for you?
Why start another thread?

--- bill

@chubbs1938

TOPIC MERGED.

Please do NOT cross post / duplicate as it wastes peoples time and efforts to have more than one post for a single topic.

Continued cross posting could result in a time out from the forum.

Could you take a few moments to Learn How To Use The Forum.
Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum.