4x20 sparkfun lcd seems broken

Hey.

I need some emergency help, our sparkfun LCD for our school project seems broken.

I was updating the software, but the upload "disconnected" the arduino, and when i finally got the new software uploaded the LCD only displays to rows of black fields, on line 1 and 3. It doesn't even show the splash screen when it is connected.

I have no idea how this happened, but would like a fix, if it is possible?

it is a 4x20 fields black on green sparkfun LCD. its a serial display, and it was connected to the arduinos tx pin when uploading the failed uploads. on the back it says ADM2004U
ver1.0

UPDATE: it seems that this is caused because I uploaded (tried to upload) a program while the LCD was connected, but i am currently unable to find a fix, and with my limited knowledge of how this works, help would be much appreciated.

Disconnect the LCD. Upload the software. Reconnect it.

If that doesn't work, more details. Like a photo.

okay, that didn't work. It should be noted that it doesnt even show its splashscreen.

some pictures:

The wiring looks correct to this novice. Could you also post the code?

Could you also post the code?

yes i can. though, i must warn you, theres quite a lot of it. Im not sure if all of it functions to my intentions, but i am, however sure that the part for the LCD functions, because i have seen it work before the update i made that changed the values used in bottom part of the code.

This is the sketch:

#include <SoftwareSerial.h>
#include <prototypeGUI.h>
#include <serialLCDFunctions.h>

#define txPin 2

prototypeGUI proto;

int dumbCurlNeutral_x = 370;
int dumbCurlNeutral_y = 305;
int dumbCurlNeutral_z = 391;

int dumbCurlMax_x = 351;
int dumbCurlMax_y = 390;
int dumbCurlMax_z = 376;

int speedOf_underarm_x;
int speedOf_underarm_y;
int speedOf_underarm_z;

int speedOf_overarm_x;
int speedOf_overarm_y;
int speedOf_overarm_z;

int underarm_x;
int underarm_y;
int underarm_z;

int overarm_x;
int overarm_y;
int overarm_z;

int oldUnderarm_x;
int oldUnderarm_y;
int oldUnderarm_z;

int oldOverarm_x;
int oldOverarm_y;
int oldOverarm_z;

int underarm_x_pin = A0;
int underarm_y_pin = A1;
int underarm_z_pin = A2;

int overarm_x_pin = A3;
int overarm_y_pin = A4;
int overarm_z_pin = A5;

int startButtonPin = 4;
int backButtonPin = 5;
int upButtonPin = 6;
int downButtonPin = 7;

int startButtonState = 0;
int backButtonState = 0;
int upButtonState = 0;
int downButtonState = 0;

int speedLedPinGreenOne = 9;
int speedLedPinGreenTwo = 10;
int speedLedPinYellowOne = 11;
int speedLedPinYellowTwo = 12;
int speedLedPinRed = 13;

int angleLedPinGreenOne = 14;
int angleLedPinGreenTwo = 15;
int angleLedPinYellowOne = 16;
int angleLedPinYellowTwo = 17;
int angleLedPinRed = 18;

int bicepAngle;
int bottomValueBicep = 0;

int startProgram = 0;
int pause = 0;

int selectionCounter = 2;

void setup(){

 pinMode(underarm_x_pin, INPUT);
 pinMode(underarm_y_pin, INPUT);
 pinMode(underarm_z_pin, INPUT);
 
 pinMode(overarm_x_pin, INPUT);
 pinMode(overarm_y_pin, INPUT);
 pinMode(overarm_z_pin, INPUT);
 
 pinMode(startButtonPin, INPUT);
 pinMode(backButtonPin, INPUT);
 pinMode(upButtonPin, INPUT);
 pinMode(downButtonPin, INPUT);
 
 delay(500);
 Serial.begin(9600);
 serialLCDFunctions::clearLCD();
 }

void loop(){

  while(startProgram == 0){
  proto.startScreen();
  if(digitalRead(startButtonPin) == HIGH){
    startProgram = 1;
    serialLCDFunctions::clearLCD();
  }
 }

while(startProgram == 1){
  proto.prototypeMenuOne();
  if(digitalRead(downButtonPin) == HIGH){
    startProgram = 2;
  serialLCDFunctions::clearLCD();}
  if(digitalRead(startButtonPin) == HIGH){
    startProgram = 3;
  serialLCDFunctions::clearLCD();}
  }
  
while(startProgram == 2){
  proto.prototypeMenuTwo();
  if(digitalRead(upButtonPin) == HIGH){
    startProgram = 1;
  serialLCDFunctions::clearLCD();}
  if(digitalRead(startButtonPin) == HIGH){
    startProgram = 2;
  serialLCDFunctions::clearLCD();}
  }
  
while(startProgram == 3){
 proto.dumbCurl();
 dumbCurlReading();
 dumbCurlAngleWrite();
 dumbCurlCount();
if(digitalRead(backButtonPin) == HIGH){
 pause = 1;
 serialLCDFunctions::clearLCD();}
 while(pause == 1){
   proto.pauseScreen();
   delay(50);
   if(digitalRead(startButtonPin) == HIGH){
     pause = 0;
     serialLCDFunctions::clearLCD();
     delay(200);
   }else if(digitalRead(backButtonPin) == HIGH){
     startProgram = 2;
     pause = 0; 
     serialLCDFunctions::clearLCD();
   }
   delay(50);
 }
 
   }
   

  
  
  
  
}


  
  
  
void initialiseAxis(){
 underarm_x = analogRead(underarm_x_pin);
 underarm_y = analogRead(underarm_y_pin);; 
 underarm_z = analogRead(underarm_z_pin);;

 overarm_x = analogRead(overarm_x_pin);
 overarm_y = analogRead(overarm_y_pin);
 overarm_z = analogRead(overarm_z_pin);
}

void angleMeasurement(){
 initialiseAxis();
  
   
}

void speedReading(){
 oldUnderarm_x = underarm_x;
 oldUnderarm_y = underarm_y;
 oldUnderarm_z = underarm_z;

 oldOverarm_x = overarm_x;
 oldOverarm_y = overarm_y;
 oldOverarm_z = overarm_z;
 
delay(300);

initialiseAxis();

speedOf_underarm_x = oldUnderarm_x - underarm_x;
speedOf_underarm_y = oldUnderarm_y - underarm_y;
speedOf_underarm_z = oldUnderarm_z - underarm_z;

speedOf_overarm_x = oldOverarm_x - overarm_x;
speedOf_overarm_y = oldOverarm_y - overarm_y;
speedOf_overarm_z = oldOverarm_z - overarm_z;

if(speedOf_underarm_x <= 0){speedOf_underarm_x * -1;}
if(speedOf_underarm_y <= 0){speedOf_underarm_y * -1;}
if(speedOf_underarm_z <= 0){speedOf_underarm_x * -1;}

if(speedOf_overarm_x <= 0){speedOf_overarm_x * -1;}
if(speedOf_overarm_y <= 0){speedOf_overarm_y * -1;}
if(speedOf_overarm_z <= 0){speedOf_overarm_z * -1;}
}

void dumbCurlReading(){
  initialiseAxis();
  bicepAngle = underarm_y;

 
  
  
}

void dumbCurlCount(){
 if(bicepAngle >= dumbCurlNeutral_y && bicepAngle <= dumbCurlNeutral_y + 5 && bottomValueBicep == 0){
  bottomValueBicep = 1; 
  digitalWrite(angleLedPinGreenOne, HIGH);
   
 }
 else if(bicepAngle >= dumbCurlMax_y - 5 && bicepAngle <= dumbCurlMax_y && bottomValueBicep == 1){
  bottomValueBicep = 0;
  proto.numberBends++; 
  digitalWrite(angleLedPinGreenOne, HIGH);
  proto.numberReps = proto.numberBends/10;
  if(proto.numberReps == 3){
    proto.numberReps = 0;
    startProgram = 1;
  
    }
  }
}

void dumbCurlAngleWrite(){
  if(bicepAngle >= dumbCurlMax_y && bicepAngle <= dumbCurlMax_y + 1 || bicepAngle <= dumbCurlNeutral_y && bicepAngle >= dumbCurlNeutral_y - 1){
   digitalWrite(angleLedPinGreenTwo, HIGH);}
   
  else if(underarm_x >= dumbCurlMax_x && underarm_x <= dumbCurlMax_x + 2 ||
          underarm_x <= dumbCurlNeutral_x - 1 && underarm_x >= dumbCurlNeutral_x - 2){
           digitalWrite(angleLedPinGreenTwo, HIGH);}
   
   else if(underarm_z >= dumbCurlMax_z && underarm_z <= dumbCurlMax_z + 2 ||
          underarm_z <= dumbCurlNeutral_z - 1 && underarm_z >= dumbCurlNeutral_z - 2){
           digitalWrite(angleLedPinGreenTwo, HIGH);}
   
   else if(bicepAngle >= dumbCurlMax_y && bicepAngle <= dumbCurlMax_y + 3 || bicepAngle <= dumbCurlNeutral_y && bicepAngle >= dumbCurlNeutral_y - 3){
   digitalWrite(angleLedPinYellowOne, HIGH);}
   
   else if(underarm_x >= dumbCurlMax_x + 2 && underarm_x <= dumbCurlMax_x + 3 ||
          underarm_x <= dumbCurlNeutral_x - 2 && underarm_x >= dumbCurlNeutral_x - 3){
   digitalWrite(angleLedPinYellowOne, HIGH);}
   
   else if(underarm_z >= dumbCurlMax_z + 2 && underarm_z <= dumbCurlMax_z + 3 ||
          underarm_z <= dumbCurlNeutral_z - 2 && underarm_z >= dumbCurlNeutral_z - 3){
   digitalWrite(angleLedPinYellowOne, HIGH);}
  
  else if(bicepAngle >= dumbCurlMax_y && bicepAngle <= dumbCurlMax_y + 5 || bicepAngle <= dumbCurlNeutral_y && bicepAngle >= dumbCurlNeutral_y - 5){
   digitalWrite(angleLedPinYellowTwo, HIGH);}
   
   else if(underarm_x >= dumbCurlMax_x + 3 && underarm_x <= dumbCurlMax_x + 4 ||
          underarm_x <= dumbCurlNeutral_x - 3 && underarm_x >= dumbCurlNeutral_x - 4){
   digitalWrite(angleLedPinYellowTwo, HIGH);}
   
   else if(underarm_z >= dumbCurlMax_z + 3 && underarm_z <= dumbCurlMax_z + 4 ||
          underarm_z <= dumbCurlNeutral_z - 3 && underarm_z >= dumbCurlNeutral_z - 4){
   digitalWrite(angleLedPinYellowTwo, HIGH);}
   
   else if(bicepAngle >= dumbCurlMax_y + 7 || bicepAngle <= dumbCurlNeutral_y -7){
   digitalWrite(angleLedPinRed, HIGH);}
   
   else if(underarm_x >= dumbCurlMax_x + 4 || underarm_x <= dumbCurlMax_x -4){
   digitalWrite(angleLedPinRed, HIGH);}
   
   else if(underarm_z >= dumbCurlMax_z + 4 || underarm_z <= dumbCurlMax_z -4){
   digitalWrite(angleLedPinRed, HIGH);} 
}

It is based on this:

#ifndef prototypeGUI_h
#define prototypeGUI_h

#include "Arduino.h"
#include "serialLCDFunctions.h"

class prototypeGUI
{
public:

	static int numberReps;
	static int numberBends;	

	void startScreen();

	void pauseScreen();
	void prototypeMenuOne();
	void prototypeMenuTwo();

	void dumbCurl();
	void tricepCurl();

private:

};

#endif

the .cpp for the prototypeGUI:

#include "Arduino.h"
#include "prototypeGUI.h"
#include "serialLCDFunctions.h"
//prototypeGUI proto;

int prototypeGUI::numberReps;
int prototypeGUI::numberBends;

void prototypeGUI::startScreen(){ 
//Definition af startskærm
serialLCDFunctions::selectLineOne();
Serial.print("  Welcome to C17's");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print(" Exercise prototype");
delay(10);
serialLCDFunctions::selectLineFour();
Serial.print("        >OK<");
delay(10);
}

void prototypeGUI::prototypeMenuOne(){
//Definition af menuen
serialLCDFunctions::selectLineOne();
Serial.print("    Choose exercise:");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print("--------------------"); //Dunno if this is something that is needed
delay(10);
serialLCDFunctions::selectLineThree();
Serial.print("dumbbell Curls <--");
serialLCDFunctions::selectLineFour();
Serial.print("Tricep Curls   ");
delay(10);
}

void prototypeGUI::prototypeMenuTwo(){
//Definition af menuen
serialLCDFunctions::selectLineOne();
Serial.print("    Choose exercise:");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print("--------------------"); //Dunno if this is something that is needed
delay(10);
serialLCDFunctions::selectLineThree();
Serial.print("dumbbell Curls ");
serialLCDFunctions::selectLineFour();
Serial.print("Tricep Curls   <--");
delay(10);
}

void prototypeGUI::tricepCurl(){
//def af tricep øvelse
serialLCDFunctions::selectLineOne();
Serial.print("Start exercise/pause");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print("Nr. of bends: ");
Serial.print(numberBends);
delay(10);
serialLCDFunctions::selectLineThree();
Serial.print("Nr. of reps.: ");
Serial.print(numberReps);
delay(10);
serialLCDFunctions::selectLineFour();
Serial.print("                Back");
delay(10);
}

void prototypeGUI::dumbCurl(){
//Definition af vægtløftøvelsen
serialLCDFunctions::selectLineOne();
Serial.print("Start exercise/pause");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print("Nr. of bends: ");
Serial.print(numberBends);//Some integer containing a loop which keeps track of how many bends you have made. (NumberBends is just something i made up)
delay(10);
serialLCDFunctions::selectLineThree();
Serial.print("Nr. of reps.: ");
Serial.print(numberReps); //Some integer containing a loop which keeps track of how many reps you have taken. (NumberReps is just something i made up)
delay(10);
serialLCDFunctions::selectLineFour();
Serial.print("                Back");
delay(10);
}

void prototypeGUI::pauseScreen(){
serialLCDFunctions::selectLineOne();
Serial.print("  paused exercise");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print("at ");
Serial.print(numberBends);
Serial.print(" Bends  ");
Serial.print(numberReps);
Serial.print(" reps");
delay(10);
serialLCDFunctions::selectLineThree();
Serial.print("  continue    quit  ");
Serial.print(numberReps); //Some integer containing a loop which keeps track of how many reps you have taken. (NumberReps is just something i made up)
delay(10);
serialLCDFunctions::selectLineFour();
Serial.print("    Start     Back  ");
delay(10);
}

This again is based on this:

called serialLCDFunctions.h and .cpp

#ifndef serialLCDFunctions_h
#define serialLCDFunctions_h

#include "Arduino.h"

class serialLCDFunctions
{
public:

	static void selectLineOne();
	static void selectLineTwo();
	static void selectLineThree();
	static void selectLineFour();

	static void goTo(int position);

	static void clearLCD();

	static void backlightOn();
	static void backlightOff();
	static void backlight50();

	static void serCommand();
	
private:

};

#endif

and the .cpp

#include "SoftwareSerial.h"
#include "Arduino.h"
#include "serialLCDFunctions.h"


//SerialLCD Functions
void serialLCDFunctions::selectLineOne(){  //puts the cursor at line 0 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(128);    //position
}
void serialLCDFunctions::selectLineTwo(){  //puts the cursor at line 2 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(192);    //position
}
void serialLCDFunctions::selectLineThree(){  //puts the cursor at line 3 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(148);    //position
}
void serialLCDFunctions::selectLineFour(){  //puts the cursor at line 4 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(212);    //position
}
void serialLCDFunctions::goTo(int position) { //position = line 1: 0-19, line 2: 20-39, etc, 79+ defaults back to 0
if (position<20){ Serial.write(0xFE);   //command flag
              Serial.write((position+128));    //position
}else if (position<40){Serial.write(0xFE);   //command flag
              Serial.write((position+128+64-20));    //position 
}else if (position<60){Serial.write(0xFE);   //command flag
              Serial.write((position+128+20-40));    //position
}else if (position<80){Serial.write(0xFE);   //command flag
              Serial.write((position+128+84-60));    //position              
} else { goTo(0); }
}
void serialLCDFunctions::clearLCD(){
   Serial.write(0xFE);   //command flag
   Serial.write(0x01);   //clear command.
}
void serialLCDFunctions::backlightOn(){  //turns on the backlight
    Serial.write(0x7C);   //command flag for backlight stuff
    Serial.write(157);    //light level.
}
void serialLCDFunctions::backlightOff(){  //turns off the backlight
    Serial.write(0x7C);   //command flag for backlight stuff
    Serial.write(128);     //light level for off.
}
void serialLCDFunctions::backlight50(){  //sets the backlight at 50% brightness
    Serial.write(0x7C);   //command flag for backlight stuff
    Serial.write(143);     //light level for off.
}
void serialLCDFunctions::serCommand(){   //a general function to call the command flag for issuing all other commands   
  Serial.write(0xFE);
}

please notice that it also uses the SoftwareSerial.h, but i will not include the code of this because its a standard arduino Library.

UPDATE: it seems that this is caused because I uploaded (tried to upload) a program while the LCD was connected, but i am currently unable to find a fix ...

This is a very good possibility. In order for any of us to help we would need to look at the datasheet for the LCD, but Sparkfun sells several different serial LCDs so we don't know which one to look at. Please provide a link to the datasheet for your specific LCD or at least let us know which device you have (the Sparkfun SKU number would identify it).

Don

It looks like you have an LCD-09568 or something very similar. This appears to be a 20x4 LCD with their 'serial backback' built right onto the main PC board. This serial interface is implemented by a PIC microcontroller which you can see in the lower right corner of your second photograph.

There are no real standards when it comes to serial interfaces for parallel LCDs. Some of them are programmed for one specific baud rate that cannot be changed by the user. These also typically have a fixed splash screen which cannot be changed either. This is somewhat limiting if you want to use a different baud rate etc, but on the other hand it's hard to inadvertently mess up the device.

On yours you can modify both of these parameters and probably a lot of other things as well. Unfortunately this also permits you to put your device into a state where you can't easily communicate with it. In your case things seem to be a lot worse because you can't even get to the splash screen. The two rows of blocks on your display means that the program in the PIC is no longer properly initializing the LCD controller and who knows what else it is doing or not doing.

There is a means to reset some aspects of the PIC, it's at the bottom of page 3 of the SerLCD datasheet, but this relies on being able to observe the splash screen and even then it isn't easy to do. There is another thread on this aspect, I'll see if I can find it later.

It looks like you may have to contact Sparkfun about your problem. The PIC microcontroller can be reprogrammed via the six pin connector at the lower left of yous second photograph. Unfortunately you would need both a programmer and the source code in order to do this yourself, maybe they will do it for you.

Don

In that case i need the code, I can borrow the programmer from our university, is the source code Open Source, or do I need that from Sparkfun?

In that case i need the code, I can borrow the programmer from our university, is the source code Open Source, or do I need that from Sparkfun?

It's not likely that it is open source and in that case it is not likely that Sparkfun would send it (or the compiled hex code for that matter) to you. But - it is worth a try.

Don

But - it is worth a try.

That depends on how long it takes for them to respond. This is for a project that we need to finish less than 16 days.

If it's that important then you should consider ordering a new display. You might want to consider a parallel LCD/serial backpack combination and you might also want to consider one of the more bulletproof (but less flexible) backpacks.

Of course, if we knew where on earth you are located some other options might be possible. There's a reason why your profile has a place for you to specify your 'location'.

Don

Sorry, didn't think about that.

Its Denmark anyways, and i know where i can buy these, i just need to know which to buy then.

is TXPin2 the correct pin?, it looks like it is connected to pin 1 (port 1) which is the normal serial pin however SoftwareSerial serial is defining pin 2 as the serial tx port It looks to me like that wire is one pin over.. After all it looks right... it is labeled TX. Possible ??

Doc

Docedison:
is TXPin2 the correct pin?, it looks like it is connected to pin 1 (port 1) which is the normal serial pin however SoftwareSerial serial is defining pin 2 as the serial tx port It looks to me like that wire is one pin over.. After all it looks right... it is labeled TX. Possible ??

Doc

The softwareserial.h must be a decoy. That's what I figure. All the functions defined and print commands in the code are using "Serial", which is the first serial port. So the connection seems correct. Too bad the display doesn't have an ATMEGA328P on it. Sparkfun actually sells that type of display. I suspect either the OP did something that damaged the MCU or somehow threw the MCU in a never-ending loop. Such thing is possible, if say the OP accidentally puts a setting command (say it's setting the display back light level) in a loop and rewrote the MCU's EEPROM 100,000 times in the matter of seconds. Then the MCU boots up once again and find all FF in the EEPROM and does something unexpected.

So OP, did you use the backlightXX functions anywhere in your code? If yes, where's the code? If no why defining the functions?

... Possible ??

It's possible, but it won't fix his current problem. According to his original post "It doesn't even show the splash screen when it is connected."

The display of the splash screen is totally independent of the Arduino. When he connects power and ground the splash screen should appear. The fact that his display shows two rows of blocks means that the LCD controller is not being properly initialized for his display. This is a function of the PIC processor, NOT the Arduino. Nothing you do with the Arduino (short of using it somehow to reprogram the PIC) will fix this.

Don

So OP, did you use the backlightXX functions anywhere in your code?

Take another look at the update in his original post. This is what did him in. It it could very well effectively give the same result as your hypothesis.

Don

floresta:

So OP, did you use the backlightXX functions anywhere in your code?

Take another look at the update in his original post. This is what did him in. It it could very well effectively give the same result as your hypothesis.

Don

I see. That uploaded arduino sketch was nothing but a random nonsense considered by the LCD MCU and some combination may have caused the MCU to change setting to something irreversible or worse cause the MCU to erase and rewrite EEPROM too many times. Probably get a different unit quick and local. 16 days is not a lot for transatlantic shipping.

If you count the pins, while looking at the labels, you will realise it is connected to the second pin the one labelled "tx" and that has worked until now.

For the rest of you guys I have another question, I can get a hold of a programmer to upload the code (whatta ya know, it is available after all: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/LCD/Monochrome/serlcd-v2_7_4line_10MHz.zip )

but how do I use one of those, and is it possible from Ubuntu? (yes, i run ubuntu 12.04 as the only system on my laptop)

[qoute]So OP, did you use the backlightXX functions anywhere in your code? If yes, where's the code? If no why defining the functions?[/qoute]

It was my plan to later integrate some sort of regulator for the light, but never got around to it. Besides, this is some code that was found on the arduino website, i just can't seem to find it again :frowning: