Offline
Newbie
Karma: 0
Posts: 10
|
 |
« on: September 06, 2011, 06:01:18 am » |
I'm trying to send a continuous feed of messages, each message about 200 chars, to the arduino, then display them one at a time, scrolling them off the screen before the next one appears. At first, it was displaying only 1 or 2 messages before it stopped. I increased my RX_BUFFER_SIZE in HardwareSerial.cpp to 1024, which has enabled me to now display closer to 15 messages, but it still stops. How do I get past the stopping part and have the messages continuously to display on the LCD?
I've tried Serial.flush, Serial.end followed by another Serial.begin, I've tried doing things with the rx buffer head and tail, etc. None of it has enabled me to achieve the non-stop display of messages I'm looking for.
Any help would be greatly appreciated?
Thanks, Tim
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6820
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #1 on: September 06, 2011, 08:08:30 am » |
You probably have to save them in an array but without seeing your code (Hint  ) it's hard to say. ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Copenhagen / Denmark
Offline
Edison Member
Karma: 5
Posts: 2338
Do it !
|
 |
« Reply #2 on: September 06, 2011, 08:31:58 am » |
Does your messages come from a PC ?
If so then i tink it would be better to implement some kind of flow control, where your Arduino will signal to the PC "hey i'm ready for the next message" If you just keep sending a stream of messages from the PC you will sooner or later run into memory issues on Arduino.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #3 on: September 06, 2011, 12:41:17 pm » |
Thanks for the replies. Does your messages come from a PC ? If so then i tink it would be better to implement some kind of flow control, where your Arduino will signal to the PC "hey i'm ready for the next message" If you just keep sending a stream of messages from the PC you will sooner or later run into memory issues on Arduino.
I get what you're saying about memory and flow control. I'm trying to figure out exactly what happens when flow control is implemented that allows you to continuously take in the next message. In that flow control process, something is reset/cleared (eg. rx buffer head & tail, pointer(s), etc.) Since I don't care if a message is lost or overwritten in the buffer once it has been written to the LCD, I either want to keep a continuous FIFO process of writing a message to the LCD and, if the buffer is full, reading in a new message to the buffer which overwrites the one that has been displayed or simply resetting the buffer each time a message is taken in and displayed so that, basically, the buffer only really holds one message at a time. You probably have to save them in an array but without seeing your code (Hint  ) it's hard to say. Unfortunately, I have many different version of the code, none of which have worked. At the moment, I'm trying to get at the underlying process of what I'd like to achieve and then start from there. The basic outline, though, seems to be one of these two: read a number of strings into the buffer -> display them FIFO on the LCD -> allow just-displayed message to be overwritten by new string taken in, which becomes the last string at the end of the queue or read in a single string -> display it on the LCD -> reset the buffer -> take in next string Hope this makes sense. Thanks again, Tim
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6820
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #4 on: September 07, 2011, 02:43:27 am » |
This seems simple enough unless I don't grasp the idea.
As you say have a FIFO of strings and print them one at a time to the LCD.
As long as the overall frequency of inputs string is <= output string printing time (bearing in mind that LCDs are very slow) there shouldn't be a problem.
If this is not the case then you will have issues, and flow control won't help.
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Copenhagen / Denmark
Offline
Edison Member
Karma: 5
Posts: 2338
Do it !
|
 |
« Reply #5 on: September 07, 2011, 04:48:16 am » |
If you have control of the code on the PC that sends the messages, then you could just implement the flow control i suggested, that would eliminate the need for any buffering beyond the single message to be displayed.
Arduino -> PC "I'm ready, send a mesage"
PC -> Arduino "mesage"
Arduino displays message
and you start over
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #6 on: September 07, 2011, 07:09:08 am » |
As long as the overall frequency of inputs string is <= output string printing time (bearing in mind that LCDs are very slow) there shouldn't be a problem.
If this is not the case then you will have issues, and flow control won't help.
Flow control WILL help, but reducing the frequency of input strings to what can be managed by the Arduino. It will shift the burden of dealing with buffering strings to the sending system, though.
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6820
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #7 on: September 07, 2011, 09:38:37 am » |
Yes, but if the overall input data speed is > the output data speed all flow control does is, as you say, shift the problem somewhere else. However I don't think that helps unless filling the PC memory and/or disk is considered a reasonable option.
Trouble is we don't know where the data is coming from, how important it is, who's reading the strings and why, are they really going to read every one.
Maybe it's OK to drop strings at the source.
OP?
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #8 on: September 08, 2011, 02:57:08 am » |
Sorry, I thought I was getting email notification whenever this thread was updated, but apparently not. I appreciate all of the responses. This seems simple enough unless I don't grasp the idea. As you say have a FIFO of strings and print them one at a time to the LCD. As long as the overall frequency of inputs string is <= output string printing time (bearing in mind that LCDs are very slow) there shouldn't be a problem. If this is not the case then you will have issues, and flow control won't help. Rob
Trust me, I'm sure I'm the one who doesn't grasp the idea. Let me try to simplify the steps for my own sake and see if that helps. 1.) Java app on PC (in this instance the PC is an android) grabs a block of messages from an online source. Could be anything -- rss feed, twitter, facebook updates, stock market quotes. Each message could be up to 200 chars in length. Block may contain as many as 100 messages, but probably will be grabbing far fewer. 2.) Parse block of messages into an array of strings. 3.) Send the individual message strings, one at a time, to the arduino via (in this particular case) bluetooth. 4.) Arduino writes the string to the LCD. 5.) Next message string is sent from PC, and it continues on. Step 1 & 2 go fine. Step 3 works to the extent that I'm getting messages on the arduino side. I start printing messages to the LCD and I run into two limits - the first being individual message length before part of the message is cut off, the second being total number of messages that print (i.e. combined number of characters for multiple messages.) The first one I can affect by increasing the "#define [sic] ByteBufferLenght" in MeetAndroid.h, but it doesn't eliminate the problem, just allows for longer messages. The second one I can affect by increasing the "#define RX_BUFFER_SIZE" in Hardware.cpp, but, once again, it doesn't eliminate the problem, just allows for more total characters. Regarding flow control, I thought I read somewhere that MeetAndroid has some flow control built in in it's send & receive functions/statements by the way it implements the arduino Hardware library. I could be mistaken, but if it didn't, wouldn't a large array of strings overflow the arduino SRAM regardless what was happening with the LCD? (Anyone who is laughing right now, remember that I said I'm sure I'm the one who doesn't grasp the idea).
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6820
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #9 on: September 08, 2011, 03:18:06 am » |
It's starting to make sense. Does it matter if a string or strings are dropped? If not then things get a lot easier. part of the message is cut off Meaning exactly what? ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #10 on: September 08, 2011, 03:44:04 am » |
It's certainly preferable if strings don't get dropped. And I guess I'm wondering why they have to.
Let's say, for instance, the block of 30 messages is grabbed and parsed. I can conceivably hold onto, update, do whatever endlessly to that array of messages on the pc/android side. And if the flow control exists already through MeetAndroid (granted, that's an assumption) then the arduino is not getting flooded with message strings, it's just getting one at a time. So, based on the fact that I was able to affect the message length and combined char limits by increasing buffer settings, it would appear that my roadblock lies within the arduino rx buffer or the lcd's ddram, or both.
It just seems that the arduino should be able to store one complete 200 char message and send it to the LCD at a rate the LCD can handle, then allow it to be overwritten in either or both buffers by the next message, rather than the following messages building up in the buffer along with ones that have already printed (which aren't needed any longer, and if they were, they still exist on the PC/android side) until those buffers are full, which is what appears to be happening. But it wouldn't be the first time I was wrong.
Cheers, Tim
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6820
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #11 on: September 08, 2011, 04:35:57 am » |
OK, I've mentioned overall throughput a few times so we'll assume that a) the overall rate of data in is < that of data out b) flow control is happening In this case all you should need is a simple ring buffer and the pseudo code should look something like this if (serial.available() != 0) { add_char_to_buffer(serial.read()); if ( buffer_nearly_full()) sendXOFF(); }
if (buffer_is_not_empty()) lcd.print (get_char_from_buffer ());
if (buffer_is_not_full()) sendXON(); ______ Rob
|
|
|
|
« Last Edit: September 08, 2011, 04:49:05 am by Graynomad »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #12 on: September 09, 2011, 02:01:42 am » |
Thanks, Rob. After doing some exhaustive testing, it appears there isn't flow control happening in the MeetAndroid send/receives that are passing my messages from the Android to the Arduino. There may be some mechanism for it already built in to the MeetAndroid library and I'm just not appending the proper end-of-message character to trigger it. I'll have to dig into it further and see if there is such a mechanism or if I need to implement something along the lines of your pseudo-code.
Your assistance is greatly appreciated.
Cheers, Tim
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #13 on: September 09, 2011, 05:01:44 pm » |
Okay, here is my first attempt to implement some flow control, but it's not working. It stops after about 10 messages. Any thoughts? #include <MeetAndroid.h> #include <LiquidCrystal.h>
#define LCD_LINES 2 #define LCD_COLUMNS 40
LiquidCrystal lcd(10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9);
/* rs: 10 rw: 13 en: 11 db0-db7: 2-9 */
MeetAndroid meetAndroid;
char msgText[160]; byte msgLength; byte charCounter; byte positionMarker; char space = ' ';
void setup() { lcd.begin(LCD_COLUMNS,LCD_LINES); Serial.begin(57600); meetAndroid.registerFunction(getMsgText, 'z'); }
void loop() { meetAndroid.receive(); }
void getMsgText(byte flag, byte numOfValues) { boolean lcdIsBusy = true; while (lcdIsBusy) { digitalWrite(13, HIGH); delay(300); lcdIsBusy = lcdBusy(); } msgLength = meetAndroid.stringLength(); meetAndroid.getString(msgText); lcd.clear(); positionMarker = 1;
// When the message length is less than the number of LCD columns, the message is written // out to the LCD, there is a pause, then the message is scrolled off to the left
if (msgLength < 42) { for (charCounter = 0; charCounter < msgLength - 1; charCounter++) { lcd.setCursor(charCounter, 1); lcd.write(msgText[charCounter]); delay(100); } delay(2000); for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) { for (int i = 0; i < LCD_COLUMNS; i++) { lcd.setCursor(i, 1); if (i + positionMarker >= msgLength - 1) { lcd.write(space); } else { lcd.write(msgText[i + positionMarker]); } } ++positionMarker; delay(175); } }
// If the message length is longer than the number of LCD columns, the first 40 chars are // written out to the LCD, then at char 41, the message scrolls left until the last char // of the message scrolls off the LCD
else { for (charCounter = 0; charCounter < LCD_COLUMNS; charCounter++) { lcd.setCursor(charCounter, 1); lcd.write(msgText[charCounter]); delay(100); } for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) { for (int i = 0; i < LCD_COLUMNS; i++) { lcd.setCursor(i, 1); if (i + positionMarker >= msgLength - 1) { lcd.write(space); } else { lcd.write(msgText[i + positionMarker]); } } ++positionMarker; delay(175); } }
}
// Checks the LCD Busy Flag
boolean lcdBusy () { int busyFlag; digitalWrite (10, LOW); // set RS to low digitalWrite (11, HIGH); // set RW to high delay(200); busyFlag = digitalRead (9); // check db7, which is pin 9 if (busyFlag == HIGH) { return true; } else { digitalWrite (11, LOW); digitalWrite (10, HIGH); digitalWrite(13, LOW); delay(200); return false; } }
Thanks, Tim
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #14 on: September 09, 2011, 08:38:34 pm » |
Found this website -- http://www.8051projects.net/lcd-interfacing/busyflag.php -- and tried to adjust my lcdBusy() function accordingly. I'm still hitting a message limit, though. So, either it's not correct and not doing what I think it's doing or it is correct and I have a buffer/flow control problem in another segment of the data path. It seems if I'm waiting to grab the next message string from the Android ( meetAndroid.getString(msgText);) until after I've made sure the LCD isn't busy, the only other place I can see these messages backing up and causing overflow is the buffer in the Arduino that holds the new string from the getString which is then copied into my char string/array variable msgText. If new messages are accumulating in that buffer rather than overwriting previous, no-longer-needed messages, then the overflow could be happening with the Arduino SRAM. I've looked for places where I could reset/flush this buffer and the only one that seems directly accessible from my code is a function in the MeetArduino library called meetArduino.flush(), which I've place right after the getString command puts the latest string into msgText -- but it doesn't seem to do anything. Any idea how to check if that buffer is actually getting cleared? Latest version of my lcdBusy function: boolean lcdBusy () { int busyFlag; pinMode(9, INPUT); // set DB7/Pin 9 to input to be able to get busy flag status digitalWrite(12, HIGH); // set EN like this because of... // http://www.8051projects.net/lcd-interfacing/busyflag.php // I don't really understand the enable pin digitalWrite(10, LOW); // set RS to low (for command register) digitalWrite(11, HIGH); // set RW to high (for reading) delay(50); busyFlag = digitalRead (9); // check status of DB7/Pin 9 if (busyFlag == HIGH) { return true; } else { pinMode(9,OUTPUT); // reset DB7/Pin 9 back to output digitalWrite(11, LOW); // reset RW back to low (for writing) digitalWrite(10, HIGH); // reset RS back to high (for data register) digitalWrite(12, LOW); // toggle EN first to low then to high because of... digitalWrite(12, HIGH); // http://www.8051projects.net/lcd-interfacing/busyflag.php delay(200); return false; } }
Latest version of my complete code: #include <MeetAndroid.h> #include <LiquidCrystal.h>
#define LCD_LINES 2 #define LCD_COLUMNS 40
LiquidCrystal lcd(10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9);
/* rs: 10 rw: 13 en: 11 db0-db7: 2-9 */
MeetAndroid meetAndroid;
char msgText[160]; byte msgLength; byte charCounter; byte positionMarker; char space = ' ';
void setup() { lcd.begin(LCD_COLUMNS,LCD_LINES); Serial.begin(57600); meetAndroid.registerFunction(getMsgText, 'z'); }
void loop() { meetAndroid.receive(); }
void getMsgText(byte flag, byte numOfValues) { boolean lcdIsBusy = true; while (lcdIsBusy) { digitalWrite(13, HIGH); delay(300); lcdIsBusy = lcdBusy(); } msgLength = meetAndroid.stringLength(); meetAndroid.getString(msgText); meetAndroid.flush(); lcd.clear(); positionMarker = 1;
// When the message length is less than the number of LCD columns, the message is written // out to the LCD, there is a pause, then the message is scrolled off to the left
if (msgLength < 42) { for (charCounter = 0; charCounter < msgLength - 1; charCounter++) { lcd.setCursor(charCounter, 1); lcd.write(msgText[charCounter]); delay(100); } delay(2000); for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) { for (int i = 0; i < LCD_COLUMNS; i++) { lcd.setCursor(i, 1); if (i + positionMarker >= msgLength - 1) { lcd.write(space); } else { lcd.write(msgText[i + positionMarker]); } } ++positionMarker; delay(175); } }
// If the message length is longer than the number of LCD columns, the first 40 chars are // written out to the LCD, then at char 41, the message scrolls left until the last char // of the message scrolls off the LCD
else { for (charCounter = 0; charCounter < LCD_COLUMNS; charCounter++) { lcd.setCursor(charCounter, 1); lcd.write(msgText[charCounter]); delay(100); } for (charCounter = LCD_COLUMNS; charCounter < msgLength + LCD_COLUMNS; charCounter++) { for (int i = 0; i < LCD_COLUMNS; i++) { lcd.setCursor(i, 1); if (i + positionMarker >= msgLength - 1) { lcd.write(space); } else { lcd.write(msgText[i + positionMarker]); } } ++positionMarker; delay(175); } }
}
// Checks the LCD Busy Flag
boolean lcdBusy () { int busyFlag; pinMode(9, INPUT); // set DB7/Pin 9 to input to be able to get busy flag status digitalWrite(12, HIGH); // set EN like this because of... // http://www.8051projects.net/lcd-interfacing/busyflag.php // I don't really understand the enable pin digitalWrite(10, LOW); // set RS to low (for command register) digitalWrite(11, HIGH); // set RW to high (for reading) delay(50); busyFlag = digitalRead (9); // check status of DB7/Pin 9 if (busyFlag == HIGH) { return true; } else { pinMode(9,OUTPUT); // reset DB7/Pin 9 back to output digitalWrite(11, LOW); // reset RW back to low (for writing) digitalWrite(10, HIGH); // reset RS back to high (for data register) digitalWrite(12, LOW); // toggle EN first to low then to high because of... digitalWrite(12, HIGH); // http://www.8051projects.net/lcd-interfacing/busyflag.php delay(200); return false; } }
Thanks, Tim
|
|
|
|
« Last Edit: September 09, 2011, 08:43:05 pm by teggroll »
|
Logged
|
|
|
|
|
|