Serial lcd strange characters

I have been working on a project & found myself running out of I/O pins, so I got a serial adapter for my 1602A LCD. I decided to start simple & used a simple sketch to show a count, however I am getting strange characters between my count numbers. Unfortunately I dont seem to be able to upload a photo of these characters, so I will attempt to describe them.
Also I am getting these same strange characters when I try a Hello World sketch (in between the words)
They each (there are only 2 different types) basically consist of 4 horizontal lines, one of the characters has a diagonal line through the bottom two horizontal lines, making it look a bit like an "equals" sign, sitting on top of a "not equals" (equals with a diagonal slash through it) sign.
The other character looks a bit like an "equals" sign, sitting on top of a strange kind of "divide" sign (equals sign a dot above and below it)

Any help would be fantastic!

so I got a serial adapter

Which one?

Also I am getting these same strange characters...

Can you find the characters on the 'Character Code' chart for your controller.

Don

Hi Floresta,
This is the adapter I got http://www.web4robot.com/LCDCtrl.html

I cannot find characters on the chart (web4robot has a link to a pdf manual on their website).

Can you think of any other information that would help us to determine what is wrong with the information that your sketch is sending to your display?

Don

I have just set up my lcd as 4bit again & have noticed the characters are appearing again. This makes me think the serial adapter is not the problem.
Could it be a bad solder joint on the header pins?

This makes me think the serial adapter is not the problem.

Can you think of something else that could be incorrect that we might want to see?

Don

I have resoldered the header pins to the LCD. This has gotten rid of the strange characters in simple sketches like Hello World.
However, they are still appearing when I send a character string to the LCD.

EDIT - I am currently using the LCD in 4 bit mode.

Here is the first part of my code:-

#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
#include <Stepper.h>

#define DIR_PIN 12
#define STEP_PIN 13

const int buttonPinLeft = 8;      // pin for the Up button
const int buttonPinRight = 9;    // pin for the Down button
const int buttonPinEsc = 10;     // pin for the Esc button
const int buttonPinEnter = 11;   // pin for the Enter button
const int buttonPinGo = 1;       // pin for Go button
int ReadGoButton;               // variable for reading go button state
int SecCount; //variable for countdown timer on lcd
int SizeVar; //variable for printing drink size when GO button is pressed
int HotCold;
int i = 0;
char* myStrings[]={"Iced","Hot"};

int Drink_Step; //variable for amount of step by motor to accomodate different drink sizes
int Drink_Size; //variable for printing drink size to lcd when GO button is pressed
long int Brew_Delay; // variable for brew time delay
int Brew_Time; //variable for printing brew time to lcd when GO button is pressed

int lastButtonPushed = 0;

int lastButtonEnterState = LOW;   // the previous reading from the Enter input pin
int lastButtonEscState = LOW;   // the previous reading from the Esc input pin
int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
int lastButtonRightState = LOW;   // the previous reading from the Right input pin


long lastEnterDebounceTime = 0;  // the last time the output pin was toggled
long lastEscDebounceTime = 0;  // the last time the output pin was toggled
long lastLeftDebounceTime = 0;  // the last time the output pin was toggled
long lastRightDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 250;    // the debounce time

// LiquidCrystal display with:
// rs on pin 2
// rw on 3
// enable on pin 6
// d4, d5, d6, d7 on pins 4, 5, 6, 7
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Rinse");
    MenuItem menu1Item2 = MenuItem("Drink Size");
      MenuItem menuItem2SubItem1 = MenuItem("16oz Iced");
      MenuItem menuItem2SubItem2 = MenuItem("12oz Hot");
      MenuItem menuItem2SubItem3 = MenuItem("16oz Hot");
    MenuItem menu1Item3 = MenuItem("Brew Time");
      MenuItem menuItem3SubItem1 = MenuItem("42 sec");
      MenuItem menuItem3SubItem2 = MenuItem("43 sec");
      MenuItem menuItem3SubItem3 = MenuItem("44 sec");
      MenuItem menuItem3SubItem4 = MenuItem("45 sec");
      MenuItem menuItem3SubItem5 = MenuItem("46 sec");
      MenuItem menuItem3SubItem6 = MenuItem("47 sec");
      MenuItem menuItem3SubItem7 = MenuItem("48 sec");   
      MenuItem menuItem3SubItem8 = MenuItem("49 sec"); 
      MenuItem menuItem3SubItem9 = MenuItem("50 sec");  
      MenuItem menuItem3SubItem10 = MenuItem("51 sec");      
    MenuItem menu1Item4 = MenuItem("Item4");
      MenuItem menuItem4SubItem1 = MenuItem("Item4SubItem1");
      MenuItem menuItem4SubItem2 = MenuItem("Item4SubItem2");
      MenuItem menuItem4SubItem3 = MenuItem("Item4SubItem3");
      MenuItem menuItem4SubItem4 = MenuItem("Item4SubItem4");
      MenuItem menuItem4SubItem5 = MenuItem("Item4SubItem5");
      MenuItem menuItem4SubItem6 = MenuItem("Item4SubItem6");      
      MenuItem menuItem4SubItem7 = MenuItem("Item4SubItem7"); 
      MenuItem menuItem4SubItem8 = MenuItem("Item4SubItem8");  
      MenuItem menuItem4SubItem9 = MenuItem("Item4SubItem9");      
    MenuItem menu1Item5 = MenuItem("Item5");
      MenuItem menuItem5SubItem1 = MenuItem("Item5SubItem1");
      
      


void setup()
{
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
  
  lcd.begin(16, 2);

  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem2SubItem3);
  menu1Item3.add(menuItem3SubItem1).addRight(menuItem3SubItem2).addRight(menuItem3SubItem3).addRight(menuItem3SubItem4).addRight(menuItem3SubItem5).addRight(menuItem3SubItem6).addRight(menuItem3SubItem7).addRight(menuItem3SubItem8).addRight(menuItem3SubItem9).addRight(menuItem3SubItem10);
  menu1Item4.add(menuItem4SubItem1).addRight(menuItem4SubItem2).addRight(menuItem4SubItem3);
  menu1Item5.add(menuItem5SubItem1);
  menu.toRoot();
  lcd.setCursor(0,0);  
  lcd.print("Clover Hacked   ");

}  // setup()...


void loop()
{

  readButtons();  //I split button reading and navigation in two procedures because 
  navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)
  
  ReadGoButton = digitalRead(buttonPinGo);
  if (ReadGoButton == HIGH) {
    lcd.setCursor(0,1);
    lcd.print(Drink_Size);
    lcd.println ("oz ");
    lcd.setCursor(6,1);
    lcd.println(myStrings[i]);
    lcd.setCursor(11,1);
    lcd.print(Brew_Time);
    lcd.println("sec   ");
    //SecCount=Brew_Time;
   // if (SecCount>0){
    //  SecCount--;}
    //  lcd.setCursor(12,1);
    //  lcd.print(SecCount);
    rotate(Drink_Step, .5);
    delay(Brew_Delay); //SET DELAY AS BREW TIME

    rotate(-Drink_Step, .25); //reverse
    delay(2000);
  }
                  
} //loop()... 

void rotate(int steps, float speed){
  //rotate a specific number of microsteps (8 microsteps per step) - (negative for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (steps > 0)? HIGH:LOW;
  steps = abs(steps);

  digitalWrite(DIR_PIN,dir); 

  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(usDelay);
  }
} 


void menuChanged(MenuChangeEvent changed){
  
  MenuItem newMenuItem=changed.to; //get the destination menu
  
  lcd.setCursor(0,1); //set the start position for lcd printing to the second row
  
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.print("Main Menu       ");
  }else if(newMenuItem.getName()=="Rinse"){
      lcd.print("Rinse           ");
       Drink_Step=4800;
       Brew_Delay=2000;  
  }else if(newMenuItem.getName()=="Drink Size"){
      lcd.print("Drink Size      ");
  }else if(newMenuItem.getName()=="16oz Iced"){
      lcd.print("16oz Iced       ");
      Drink_Size=16;
      i = 0;
      Drink_Step=1600;
  }else if(newMenuItem.getName()=="12oz Hot"){
      lcd.print("12oz Hot        ");
      Drink_Size=12;
      i = 1;
      Drink_Step=3200;
  }else if(newMenuItem.getName()=="16oz Hot"){
      lcd.print("16oz Hot        ");
       Drink_Size=16;
       i = 1;
       Drink_Step=4800;     
  }else if(newMenuItem.getName()=="Brew Time"){
      lcd.print("Brew Time       ");
  }else if(newMenuItem.getName()=="42 sec"){
      Brew_Time=42;
      lcd.print("42 sec          ");  
      Brew_Delay=42000;  
  }else if(newMenuItem.getName()=="43 sec"){
      Brew_Time=43;
      lcd.print("43 sec          "); 
      Brew_Delay=43000;  
  }else if(newMenuItem.getName()=="44 sec"){
      Brew_Time=44;
      lcd.print("44 sec          "); 
      Brew_Delay=44000;        
  }else if(newMenuItem.getName()=="45 sec"){  
      Brew_Time=45;
      lcd.print("45 sec          "); 
      Brew_Delay=45000;        
  }else if(newMenuItem.getName()=="46 sec"){  
      Brew_Time=46;
      lcd.print("46 sec          ");  
      Brew_Delay=46000;        
  }else if(newMenuItem.getName()=="47 sec"){
      Brew_Time=47;
      lcd.print("47 sec          "); 
      Brew_Delay=47000;        
  }else if(newMenuItem.getName()=="48 sec"){
      Brew_Time=48;
      lcd.print("48 sec          "); 
      Brew_Delay=48000;        
  }else if(newMenuItem.getName()=="49 sec"){
      Brew_Time=49;  
      lcd.print("49 sec          ");  
      Brew_Delay=49000;        
  }else if(newMenuItem.getName()=="50 sec"){   
      Brew_Time=50;    
      lcd.print("50 sec          "); 
      Brew_Delay=50000;        
  }else if(newMenuItem.getName()=="51 sec"){
      Brew_Time=51;    
      lcd.print("51 sec          "); 
      Brew_Delay=51000;        
  }else if(newMenuItem.getName()=="Item4"){
      lcd.print("Brew Temp       ");    
  }else if(newMenuItem.getName()=="Item4SubItem1"){
      lcd.print("200F            ");  
  }else if(newMenuItem.getName()=="Item4SubItem2"){
      lcd.print("205F            ");   
  }else if(newMenuItem.getName()=="Item4SubItem3"){
      lcd.print("210F            ");    
  }
}

and here is the rest -

void menuUsed(MenuUseEvent used){
 //lcd.setCursor(0,0);  
  lcd.setCursor(0,1); 
  lcd.print(used.item.getName());
  lcd.print(" selected");
  delay(3000);  //delay to allow message reading
  lcd.setCursor(0,0);  
  //lcd.print("www.coagula.org");
  menu.toRoot();  //back to Main
}


void  readButtons(){  //read buttons status
  int reading;
  int buttonEnterState=LOW;             // the current reading from the Enter input pin
  int buttonEscState=LOW;             // the current reading from the input pin
  int buttonLeftState=LOW;             // the current reading from the input pin
  int buttonRightState=LOW;             // the current reading from the input pin

  //Enter button
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEnter);

                  // check to see if you just pressed the enter button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEnterState) {
                    // reset the debouncing timer
                    lastEnterDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastEnterDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEnterState=reading;
                    lastEnterDebounceTime=millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEnterState = reading;
                  

    //Esc button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEsc);

                  // check to see if you just pressed the Down button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEscState) {
                    // reset the debouncing timer
                    lastEscDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastEscDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEscState = reading;
                    lastEscDebounceTime=millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEscState = reading; 
                  
                     
   //Down button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinRight);

                  // check to see if you just pressed the Down button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonRightState) {
                    // reset the debouncing timer
                    lastRightDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastRightDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonRightState = reading;
                   lastRightDebounceTime =millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonRightState = reading;                  
                  
                  
    //Up button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinLeft);

                  // check to see if you just pressed the Down button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonLeftState) {
                    // reset the debouncing timer
                    lastLeftDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastLeftDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonLeftState = reading;
                    lastLeftDebounceTime=millis();;
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonLeftState = reading;  

                  //records which button has been pressed
                  if (buttonEnterState==HIGH){
                    lastButtonPushed=buttonPinEnter;

                  }else if(buttonEscState==HIGH){
                    lastButtonPushed=buttonPinEsc;

                  }else if(buttonRightState==HIGH){
                    lastButtonPushed=buttonPinRight;

                  }else if(buttonLeftState==HIGH){
                    lastButtonPushed=buttonPinLeft;

                  }else{
                    lastButtonPushed=0;
                  }                  
}

void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();
  
  switch (lastButtonPushed){
    case buttonPinEnter:
      if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
        menu.use();
      }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
        menu.moveDown();
       } 
      break;
    case buttonPinEsc:
      menu.toRoot();  //back to main
      break;
    case buttonPinRight:
      menu.moveRight();
      break;      
    case buttonPinLeft:
      menu.moveLeft();
      break;      
  }
  
  lastButtonPushed=0; //reset the lastButtonPushed variable
}

Now that I can finally see the sketch your problem is obvious. The LiquidCrystal library is used when your LCD is connected via it's native parallel interface to your Arduino. You are using a serial interface so your sketch must send commands that are understood by the processor on the serial interface card. It's time for you to read the 'web4robot' documentation.

Don

As I stated above, I resoldered the header pins and changed back to 4 bit mode.

I am still getting the strange characters, but only when I use the line

    lcd.println(myStrings[i]);

All other lcd.print commands are no longer producing this problem.

One of us is seriously confused. From your topic heading any your original post you claim to be using a serial interface. When you finally posted your code I could see that you are using a library that is designed for a parallel interface. Your sketch must interface with the serial adapter and the LiquidCrystal library will not do that for you. The serial adapter may or may not be using a 4-bit interface and you have no control over which one is being used since that refers to the interface between the microprocessor on your serial adapter and the LCD module connected to that adapter. Since you are using a serial interface I would also expect to see some 'serial' commands such as serial.begin etc. If what I am saying doesn't make sense then you will have to post a photograph of your setup so I can figure it out.

Don

I removed the serial adapter in an attempt to simplify the problem. Im currently using a standard 1602A LCD in 4 bit mode. There is NOT currently a serial adapter in the circuit.

However I am still getting the strange characters from the code

lcd.println(myStrings[i]);

Sorry, my crystal ball isn't working. Is there anything else I should know or is this some sort of a test?

For starters this won't work:

// LiquidCrystal display with:
// rs on pin 2
// rw on 3
// enable on pin 6
// d4, d5, d6, d7 on pins 4, 5, 6, 7
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

However I am still getting the strange characters from the code

lcd.println(myStrings[i]);

That doesn't surprise me, shouldn't you stick to the valid LiquidCrystal functions?

Don

rosscopicotrain:
I removed the serial adapter in an attempt to simplify the problem. Im currently using a standard 1602A LCD in 4 bit mode. There is NOT currently a serial adapter in the circuit.

However I am still getting the strange characters from the code

lcd.println(myStrings[i]);

lcd has no valid println as far as I know. It does have print.

Rossco...

Here is your assignment. If you successfully complete it then you probably won't need any more help in getting your LCD to function in your original project.

  1. Get the regular "Hello World" sketch functioning on your LCD. You can follow the tutorial at Arduino Tutorial - connecting a parallel LCD if you are having any problems. You don't have to use the same Arduino pins used there but make sure that you fix what was wrong with your setup (pointed out in reply # 12).

  2. Modify the sketch so that the second line displays a message with a fixed part and a variable part. The fixed part should be something like "Count = ", and the variable part should be a number that is initially 0 and then periodically increases to 255 or so before repeating. I suggest about 5 or 10 characters per second so you can see the count change but you don't have to wait too long for the count to repeat.

  3. If you have extraneous characters displayed after your first count then fix that up.

  4. If you used the lcd.clear() function then go back and use a different technique.

  5. If you have to repeat the display of the fixed part of the message then go back and use a different technique.

  6. When all this is working then recreate the functionality of this final sketch using your serial interface board.

Don

The problem is with the use of lcd.println. Check out this thread: (Resolved) Weird Characters following Proper Text on 1602 LCD - Displays - Arduino Forum