Go Down

Topic: *Solved- I think* LCD random character display but Serial output fine (Read 21820 times) previous topic - next topic

BassnHarp

Feb 12, 2012, 03:31 am Last Edit: Feb 12, 2012, 04:10 am by BassnHarp Reason: 1
* Solved - after reading the basic Hello World tutorial again I added the 10K pot, instead of the pin 9 contrast control, and things seem fine.  I did wire it originally based on another diagram using pin 9 to feed the VO, but evidently that was not working consistently. I am going to go back and look that one up to see if I missed something.
*
Trying to figure out some strange behavior of my LCD.  Anyway the example code runs fine for a period of time but usually after a minute or so I start to see random characters on the LCD but the serial monitor shows the correct words.  Can someone else run this with a simple LCD set up and see if it maybe is bad hardware that I have.  This is pretty much my first project, obviously a pear down version to isolate the issue I'm having, so I don't have an extra LCD to try it on.

Code: [Select]

/*
* Simple test program to demonstrate issue I am having with a
* LCD display and working with char arrays.
* After some random amount of cylces, usually before one minute has
* elapsed the LCD display goes haywire, displaying
* crazy characters and then it will come back to
* normal.  Could it be hardware or wiring?  I am using
* a breadboard, standard 16x2 LCD, wired like the example code
* for the LCD, could one of the wires be intermittently bad or the
* LCD itself?  I was thinking memory leak but the serial display
* show the words normal, so it has to have something to do with the LCD.
*/

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int CONTRAST_PIN = 9;
const int BACKLIGHT_PIN = 7;
const int CONTRAST = 100;

void setup()
{
 Serial.begin(9600);   // opens serial port  
 // Switch on the backlight and LCD contrast levels
 pinMode(CONTRAST_PIN, OUTPUT);
 pinMode(BACKLIGHT_PIN, OUTPUT);

 digitalWrite(BACKLIGHT_PIN, HIGH);
 analogWrite (CONTRAST_PIN, CONTRAST);
   
 lcd.begin(16,2);               // initialize the lcd
 lcd.home ();                   // go home
 lcd.print("   LCD Test");  
 lcd.setCursor ( 0, 1 );        // go to the next line
 lcd.print (" Initializing  ");
}

char lcdLines[2][17];

boolean bSerial = true;
boolean bLcd = true;

void loop()
{

 char * strOnOff[] = {"On", "Off"} ;
 char * strRelay[] = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"};
 int iRelayPos = 0;
 int iStatePos = 0;
 int iLen = 0;
 
 while(1)  // loop so variables don't get initialized each loop
 {
   // clear the two LCD storage lines
   strcpy(lcdLines[0],"");
   strcpy(lcdLines[1],"");
       
   add2Message("* Relay State *");
   add2Message(strRelay[iRelayPos]);
   add2Message("is");
   add2Message(strOnOff[iStatePos]);

   if (bSerial) {
     Serial.println(lcdLines[0]);
     Serial.println(lcdLines[1]);
   }

   if (bLcd) {
     lcd.clear();    
     iLen = int((16 - strlen(lcdLines[0])) / 2); // center the text
     lcd.setCursor(iLen,0);      
     lcd.print(lcdLines[0]);
     iLen = int((16 - strlen(lcdLines[1])) / 2); // center the text
     lcd.setCursor(iLen,1);      
     lcd.print(lcdLines[1]);
     lcd.noCursor();
   }
   
  // random stuff for testing
  iRelayPos = random(0,11);
  iStatePos = random(0,2);
  delay(2000);  
     
 }
 
} // End of loop()


/* Add the messages to either the first line or the second
  depending on if there is enough room on line one.
  A simple word wrap routine.
*/
void add2Message(const char *source) {
 int iLen;
 
 iLen = strlen(lcdLines[0]);
 iLen = (iLen + strlen(source));
 iLen = (iLen + 1);
 if  ((iLen <= 16) && (strlen(lcdLines[1]) == 0)) {
   if (strlen(lcdLines[0]) != 0) {strcat(lcdLines[0]," ");}  
   strcat(lcdLines[0],source);
 }
 else {
   if (strlen(lcdLines[1]) != 0) {strcat(lcdLines[1]," ");}  
   strcat(lcdLines[1],source);
 }    
}


winner10920

It is probably interference or a loose connection, do you have it on a breadboard?

John_S

Glad you found the problem. I don't think a PWM will control the contrast satisfactory without a filter.
Just another point, put your variables in the setup() so you don't need to do a while(1) loop within the loop().

BassnHarp

Would putting them in the setup() make them global?  Or would I need to put them outside of the setup() like I did with the Boolean's?

John_S

Read the code comments below. I tried to illustrate the point :)
Code: [Select]
int GlobalVariable; //this will work in all funcions

void Setup(){
  int LocalSetupVariable = 200;  //this will only work in Setup
  GlobalVariable = 100;         //this works here because it is declared as a global variable
}

void loop(){
  int LocalLoopVariable = 300;  //this will only work in loop
 
  Serial.print(GlobalVariable + LocalLoopVarable); //this will print 400
  Serial.print(GlobalVariable + LocalSetupVarable); //this won't work. LocalSetupVariable is not declared in loop.

}

komalkristina

hey
ive got my code working and im able to see the output on the serial monitor but when i go to display this onto my lcd random characters show up instead of the characters.

im using arduino uno, arduino ethernet and 16x2 lcd

here is my code
Code: [Select]
// include the library code:
#include <LiquidCrystal.h>
#include <SPI.h>
#include <Ethernet.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

byte server[] = { 212,1,210,253 }; //ip Address of the server you will connect to

//The location to go to on the server
//make sure to keep HTTP/1.0 at the end, this is telling it what type of file it is
String location = "/output.php HTTP/1.0";

// if need to change the MAC address (Very Rare)
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x0A, 0xA0 };

////////////////////////////////////////////////////////////////////////

EthernetClient client;

char inString[190]; // string for incoming serial data
int stringPos = 0; // string index counter
boolean startRead = false; // is reading?

void setup()
{
  lcd.begin(16,2);
  Ethernet.begin(mac);
  Serial.begin(9600);
}

void loop()
{
  String pageValue = connectAndRead(); //connect to the server and read the output
  Serial.println(pageValue); //print out the findings.
  lcd.print(pageValue);
  delay(8000); //wait 8 seconds before connecting again
}

String connectAndRead()
{
  //connect to the server

  Serial.println("connecting...");

  //port 80 is typical of a www page
  if (client.connect(server, 80))
  {
    Serial.println("connected");
    client.print("GET ");
    client.println(location);
    client.println();

    //Connected - Read the page
    return readPage(); //go and read the output

  }
  else
  {
    return "connection failed";
  }

}

String readPage()
{
  //read the page, and capture & return everything between '<' and '>'
  stringPos = 0;
  memset( &inString, 0, 190 ); //clear inString memory

  while(true)
  {
    if (client.available())
    {
      char c = client.read();

      if (c == '<' )
      { //'<' is our begining character
        startRead = true; //Ready to start reading the part
      }
      else if(startRead)
      {

        if(c != '>')
        { //'>' is our ending character
          inString[stringPos] = c;
          stringPos ++;
        }
        else
        {
          //got what we need here! We can disconnect now
          startRead = false;
          client.stop();
          client.flush();
          Serial.println("disconnecting.");
          return inString;
        }
      }
    }
  }
}




please help me :)

komalkristina

hey...Ive got my code working and i can see the output on the serial monitor
but when i go to display the output to my 16x2 lcd random characters get displayed instead of the actual output
here is my code
Code: [Select]
// include the library code:
#include <LiquidCrystal.h>
#include <SPI.h>
#include <Ethernet.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

byte server[] = { 212,1,210,253 }; //ip Address of the server you will connect to

//The location to go to on the server
//make sure to keep HTTP/1.0 at the end, this is telling it what type of file it is
String location = "/output.php HTTP/1.0";

// if need to change the MAC address (Very Rare)
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x0A, 0xA0 };

////////////////////////////////////////////////////////////////////////

EthernetClient client;

char inString[190]; // string for incoming serial data
int stringPos = 0; // string index counter
boolean startRead = false; // is reading?

void setup()
{
  lcd.begin(16,2);
  Ethernet.begin(mac);
  Serial.begin(9600);
}

void loop()
{
  String pageValue = connectAndRead(); //connect to the server and read the output
  Serial.println(pageValue); //print out the findings.
  lcd.print(pageValue);
  delay(8000); //wait 8 seconds before connecting again
}

String connectAndRead()
{
  //connect to the server

  Serial.println("connecting...");

  //port 80 is typical of a www page
  if (client.connect(server, 80))
  {
    Serial.println("connected");
    client.print("GET ");
    client.println(location);
    client.println();

    //Connected - Read the page
    return readPage(); //go and read the output

  }
  else
  {
    return "connection failed";
  }

}

String readPage()
{
  //read the page, and capture & return everything between '<' and '>'
  stringPos = 0;
  memset( &inString, 0, 190 ); //clear inString memory

  while(true)
  {
    if (client.available())
    {
      char c = client.read();

      if (c == '<' )
      { //'<' is our begining character
        startRead = true; //Ready to start reading the part
      }
      else if(startRead)
      {

        if(c != '>')
        { //'>' is our ending character
          inString[stringPos] = c;
          stringPos ++;
        }
        else
        {
          //got what we need here! We can disconnect now
          startRead = false;
          client.stop();
          client.flush();
          Serial.println("disconnecting.");
          return inString;
        }
      }
    }
  }
}




do i have to covert these characters somehow and then display it?

thanks

bubulindo

#7
Oct 15, 2012, 11:10 am Last Edit: Oct 15, 2012, 11:26 am by bubulindo Reason: 1
Are the pins in the initialization of the LCD correct?

Also, you should clear the LCD before writing to it again.

Have you tried something like this

Code: [Select]
// include the library code:
#include <LiquidCrystal.h>
#include <SPI.h>
#include <Ethernet.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

byte server[] = { 212,1,210,253 }; //ip Address of the server you will connect to

//The location to go to on the server
//make sure to keep HTTP/1.0 at the end, this is telling it what type of file it is
String location = "/output.php HTTP/1.0";

// if need to change the MAC address (Very Rare)
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x0A, 0xA0 };

////////////////////////////////////////////////////////////////////////

EthernetClient client;

char inString[190]; // string for incoming serial data
int stringPos = 0; // string index counter
boolean startRead = false; // is reading?

void setup()
{
  lcd.begin(16,2);
  Ethernet.begin(mac);
  Serial.begin(9600);
  lcd.clear();
  lcd.print("hello, world!!");
}

void loop()
{
}



This... is a hobby.

PaulS

The art of getting good answers lies in asking good questions.

PaulS

This is the third active thread in this section of the forum with the same code in it. OP, knock it off. One thread is all you need, and one user ID. More will NOT get you more help. What it will get is us pissed off for wasting our time.
The art of getting good answers lies in asking good questions.

nickgammon

Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

anroots


Glad you found the problem. I don't think a PWM will control the contrast satisfactory without a filter.


You are correct - at least this was of help to me.

I had an 16x2 LCD with Atmega328 on a breadboard and a simple test sketch that displayed millis() every 200ms was acting strange: it would work OK for about 4 seconds, then display some random gibberish characters, then work OK. I debugged programming and even the crystal and caps, but nada. Then I found this.

I was controlling the backlight and contrast of the LCD with PWM pins. Turns out PWM doesn't go so well to the V0 pin. Everything worked OK after I removed PWM from V0 and used a simple pot.

PaulS

Quote
Turns out PWM doesn't go so well to the V0 pin.

Interesting. Probably setting up noise (harmonics?) in the LCD as the light was turned on and off.
The art of getting good answers lies in asking good questions.

MakerSelf

****Background****

I also had this issue, as I was trying to control the contrast pin using a PWM output from an Uno board, rather than from a physical pot.

I found that when controlling V0 from the PWM this caused random characters to appear of the LCD after varying amounts of time, while controlling V0 from the physical pot caused it to be stable.  Note that I still controlled the backlight from the Uno board, using a digital output pin, and this worked fine.  More here if interested:  http://makerself.wordpress.com/2014/12/08/getting-a-16x2-lcd-screen-to-work-and-developing-a-lcd-contrast-tester/


****My question is this****

What is it about the PWM output that causes this issue?  And any thoughts on how to solve this?  I would be very keen to have LCD contrast be adjustable by software, rather than hardware.

I am thinking of two potential solutions to 'clean' the PWM output, but am not sure if these will work as I am not sure what it is about the PWM output that causes these issue.


>>>>Option 1>>:  put in a capacitor between the PWM output and ground, as maybe the PWM output has some spikes that need to moderated that are causing the issue.

>>>>Option 2>>:  have the V0 pin (which controls the contrast) connected to a supply that is controlled by a transistor.  This way, the PWM pin on the Uno can control the transistor gate (if MOSFET) or base (if BJT), which would adjust the voltage on the V0 pin.  This is because I suspect that it is the variable nature of the PWM which causes the issue vs. the continuous current from the pot.


My questions are:
1) Any advice on how to do this (control V0 by software)?
2) Which of these options would be the better approach (or another approach that I have not thought of)? 
3) If the transistor is the way to go, which of a MOSFET or BJT would be the best for ensuring a continuous current at the V0 pin?

Thanks!

MakerSelf

Hello all,

I was advised that I should probably start a new topic instead of posting this question here as this is an old post and slightly different topic, so I have posted this question in the Displays section instead.

The new post is at:  http://forum.arduino.cc/index.php?topic=284781.0

Please go there to reply.  Apologies for the cross posting, and hope this linking can minimize any cross traffic, and also help anyone who comes across this post looking for the answer I am seeing to find the result.

Cheers!

Go Up