Go Down

Topic: Serial Graphic LCD 84x48 SGD-A (Read 1 time) previous topic - next topic

imagitronics

Hey all, I'm trying to interface my Arduino with the Serial Graphic LCD 84x48 SGD-A from Sparkfun.

The following is a snippet of code including some of the functions that I'm using to communicate with the display:

Code: [Select]

void setup() {
 beginSerial(9600);
 
 print("Let's test this.");
 delay(1000);
 sleep();
 delay(1000);
 wake();
 delay(1000);
 printf("That worked nicely!");
}

void loop() {
}

void print(char string[]) {
 Serial.print('S', BYTE);
 Serial.print(sizeof(string));
 Serial.print(string);
}

void ping() {
 Serial.print('X', BYTE);
}

void wake() {
 char result = 'Z';
 do {
   ping();
   //delay(100);
   if(Serial.available() > 0) {
     result = Serial.read();
   }
 } while(result != 'X');
}

void sleep() {
 Serial.print('Z', BYTE);
}


The problem is that once I print() none of my other functions will work. Instead they print their "control characters" to the LCD display. It's as if I'm "stuck" in "string" mode. To be thorough, I also tried looping through a null terminated string and sending the BYTES individually, (and replacing sizeof()) but  no matter what I do, I'm stuck in text mode after writing to the display. Any suggestions?

Thanks,
Tim

imagitronics

#1
Sep 08, 2007, 05:00 pm Last Edit: Sep 08, 2007, 05:01 pm by imagitronics Reason: 1
I wanted to be thorough, and troubleshoot this at the lowest possible level, so I used this code snippet:

Code: [Select]

void setup() {
 beginSerial(9600);
 
 // this part works
 Serial.print('P', BYTE);  // move cursor
 Serial.print(20);         // x=20
 Serial.print(20);         // y=20
 
 // this part works
 Serial.print('S', BYTE);  // begin string
 Serial.print(4);          // length of string
 Serial.print('T', BYTE);  
 Serial.print('E', BYTE);
 Serial.print('S', BYTE);
 Serial.print('T', BYTE);
 
 // this part is displayed onscreen instead of moving the cursor
 Serial.print('P', BYTE);  // move cursor
 Serial.print(40);         // x=40
 Serial.print(40);         // y=40
 
 // this part works
 Serial.print('S', BYTE);  // begin string
 Serial.print(4);          // length of string
 Serial.print('T', BYTE);  
 Serial.print('E', BYTE);
 Serial.print('S', BYTE);
 Serial.print('T', BYTE);
}


The end result looks something like, "          TESTP4040S4TEST" on the LCD display. As you can see, the first "move cursor" operation worked fine, but once I issue any text commands, the LCD never recovers.

Any help would be greatly appreciated.

Horace

Read the documentation for Serial.print.

http://www.arduino.cc/en/Serial/Print

You don't want Serial.print(4), you want Serial.print(4,BYTE).  You're printing the ascii value of 4, and the LCD thinks your string is very long.

imagitronics

I wish that were true. I've actually tried:

Serial.print(4,BYTE);
Serial.print('4', BYTE);
Serial.print(4, DEC);
Serial.print('4', DEC);
Serial.print(4);

etc. Sending BYTE is actually worse because it won't even send the entire string, ie.
Serial.print('S', BYTE);
Serial.print(7, BYTE);
Serial.print("Testing");

may only display "Te" to the screen.

Horace

That looks correct, it should be working.  Are there any other commands before the S command?  Strip your program down to nothing, just the S command.  Try substituting other values for 7 (even though 7 is the correct value).  Are you monitoring serial communications in the Arduino IDE?  Maybe you could get it written to a file and do a hex dump?  I've barely used the Serial object before, but I'm pretty certain you're using it correctly in the last bit of code you posted.

imagitronics

#5
Sep 09, 2007, 11:11 am Last Edit: Sep 09, 2007, 11:50 am by imagitronics Reason: 1
[EDIT] I was totally unaware that we had access to the entire standard C library from arduino. That is awesome. The code now works perfectly. I added a strcat to append a null terminator to printed text. This is to prevent buffer overflows.

Code: [Select]

void print(char string[]) {
 strcat(string, "\0");
 Serial.print('S', BYTE);
 Serial.print(strlen(string), BYTE);
 Serial.print(string);
}


[/EDIT]

I got it working. When I was passing char[] to the print() function it was being passed as a pointer, so sizeof() returned 1, apparently causing all sorts of chaos. I tried to find an elegant solution, but a friend of mine who is comfortable with C suggested that I use null-terminated strings, or pass the length as a parameter, so I created an overloaded function like so:

Code: [Select]

void print(char string[], int length) {
 Serial.print('S', BYTE);
 Serial.print(length, BYTE);
 Serial.print(string);
}

void print(char string[]) {
 Serial.print('S', BYTE);
 Serial.print(strlen(string), BYTE);
 Serial.print(string);
}

int strlen(char str[]) {
 int i;
 for(i=0; i<=255; i++) {
   if(str[i]=='\0') {
     return(i);
   }
 }
}


It can be used as either print("Junk", 4); or print("Junk\0");

If anyone has a better solution, please let me know. Otherwise, it works.

Thanks for your help Horace.
Tim

Horace

String literals are nul-terminated anyway.  In fact, strcat(str,"\0") should be a no-op.  You'd be adding a nul byte to a memory location that already contains a nul byte, and you're calling strcat with a zero-length string which does nothing.  C string functions have no way to differentiate an empty string literal "" from a string literal with a nul as its first byte "\0more string here".

Your code now is exactly the same as your code before.  You shouldn't even need "Junk\0", since the string literal "Junk" already has a nul byte at the end.

imagitronics

It does function as a noop, but a useful one. It prevents buffer overflows like:

char a[3] = {65, 67, 64};
print(a);

so it allows me to print strings that may not have been input as string literals.

Thanks again for the help Horace.
Tim

Horace

Actually, it doesn't.  The strcat function doesn't know how long the string is, it'll seek from the beginning of the string until it finds a nul byte.  And replacing a nul byte with a nul byte, well..  doesn't do much, does it?  It's best to either use string literals (which are nul-terminated) or nul terminate your strings as they are input.

Go Up
 

Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Note: this post will not display until it's been approved by a moderator.
Name:
Email:

shortcuts: alt+s submit/post or alt+p preview